/* ----------------------------------------------------------------------------
 * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
 * Description: LiteOS Mem Module Implementation
 * Author: shaodongdong
 * Create: 2013-01-01
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific prior written
 * permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------------
 * Notice of Export Control Law
 * ===============================================
 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
 * applicable export control laws and regulations.
 * --------------------------------------------------------------------------- */

#include "los_memory_pri.h"
#include "los_multipledlinkhead_pri.h"
#include "los_memstat_pri.h"
#include "los_task_pri.h"
#include "los_exc.h"
#ifdef LOSCFG_LIB_LIBC
#include "string.h"
#include "stdio.h"
#endif
#ifdef LOSCFG_MEM_RECORDINFO
#include "los_memrecord_pri.h"
#endif

#ifdef LOSCFG_SHELL_EXCINFO
#include "los_excinfo_pri.h"
#endif

#define NODEDUMPSIZE  64  /* the dump size of current broken node when memcheck error */
#define COLUMN_NUM    8   /* column num of the output info of mem node */

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */

/**
 * @ingroup los_memory
 * Memory pool information structure
 */
typedef struct {
    VOID *pool;      /**< Starting address of a memory pool  */
    UINT32 poolSize; /**< Memory pool size    */
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    UINT32 poolWaterLine;   /**< Maximum usage size in a memory  pool  */
    UINT32 poolCurUsedSize; /**< Current usage size in a memory  pool  */
#endif
#ifdef LOSCFG_MEM_MUL_POOL
    VOID *nextPool;
#endif
} LosMemPoolInfo;

/**
 * @ingroup los_memory
 * Memory linked list control node structure
 */
typedef struct {
    LOS_DL_LIST freeNodeInfo;         /**< Free memory node  */
    struct tagLosMemDynNode *preNode; /**< Pointer to the previous memory node */

#ifdef LOSCFG_MEM_HEAD_BACKUP
    UINT32 gapSize;
    AARCHPTR checksum; /**< magic = xor checksum> */
#endif

#ifdef LOSCFG_MEM_RECORDINFO
    UINT32 originSize;
#ifdef LOSCFG_AARCH64
    UINT32 reserve1;
#endif
#endif

#ifdef LOSCFG_MEM_LEAKCHECK
    AARCHPTR linkReg[LOS_RECORD_LR_CNT];
#endif

#ifdef LOSCFG_AARCH64
    UINT32 reserve2;
#endif
    /**< Size and flag of the current node (the high two bits represent a flag,and the rest bits specify the size) */
    UINT32 sizeAndFlag;
} LosMemCtlNode;

/**
 * @ingroup los_memory
 * Memory linked list node structure
 */
typedef struct tagLosMemDynNode {
#ifdef LOSCFG_MEM_HEAD_BACKUP
    LosMemCtlNode backupNode;
#endif
    LosMemCtlNode selfNode;
} LosMemDynNode;

#ifdef LOSCFG_MEM_MUL_POOL
VOID *g_poolHead = NULL;
#endif

#ifdef LOSCFG_MEM_HEAD_BACKUP
static VOID OsMemNodeSave(LosMemDynNode *node);
#define OS_MEM_TASKID_SET(node, ID)                                                           \
    do {                                                                                      \
        AARCHPTR tmp_ = (AARCHPTR)(((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext); \
        tmp_ &= 0xffff0000;                                                                   \
        tmp_ |= (ID);                                                                         \
        ((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext = (LOS_DL_LIST *)tmp_;       \
        OsMemNodeSave ((LosMemDynNode *)(node));                                              \
    } while (0)
#else
#define OS_MEM_TASKID_SET(node, ID)                                                           \
    do {                                                                                      \
        AARCHPTR tmp_ = (AARCHPTR)(((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext); \
        tmp_ &= 0xffff0000;                                                                   \
        tmp_ |= (ID);                                                                         \
        ((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext = (LOS_DL_LIST *)tmp_;       \
    } while (0)
#endif
#define OS_MEM_TASKID_GET(node) ((AARCHPTR)(((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext) & 0xffff)

#ifdef LOSCFG_MEM_HEAD_BACKUP
#define OS_MEM_MODID_SET(node, ID)                                                            \
    do {                                                                                      \
        AARCHPTR tmp_ = (AARCHPTR)(((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext); \
        tmp_ &= 0xffff;                                                                       \
        tmp_ |= (ID) << 16;                                                                   \
        ((LosMemDynNode *)node)->selfNode.freeNodeInfo.pstNext = (LOS_DL_LIST *)tmp_;         \
        OsMemNodeSave ((LosMemDynNode *)(node));                                              \
    } while (0)
#else
#define OS_MEM_MODID_SET(node, ID)                                                            \
    do {                                                                                      \
        AARCHPTR tmp_ = (AARCHPTR)(((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext); \
        tmp_ &= 0xffff;                                                                       \
        tmp_ |= (ID) << 16;                                                                   \
        ((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext = (LOS_DL_LIST *)tmp_;       \
    } while (0)
#endif
#define OS_MEM_MODID_GET(node) (((AARCHPTR)(((LosMemDynNode *)(node))->selfNode.freeNodeInfo.pstNext) >> 16) & 0xffff)

#define OS_MEM_ALIGN(p, alignSize) (((AARCHPTR)(p) + (alignSize) - 1) & (~((AARCHPTR)((alignSize) - 1))))
#define OS_MEM_NODE_HEAD_SIZE      sizeof(LosMemDynNode)
#define OS_MEM_MIN_POOL_SIZE       (OS_DLNK_HEAD_SIZE + 2 * OS_MEM_NODE_HEAD_SIZE + sizeof(LosMemPoolInfo))
#define IS_POW_TWO(value)          ((((AARCHPTR)(value)) & ((AARCHPTR)(value) - 1)) == 0)
#define POOL_ADDR_ALIGNSIZE         64
#ifdef LOSCFG_AARCH64
#define OS_MEM_ALIGN_SIZE 8
#else
#define OS_MEM_ALIGN_SIZE 4
#endif
#define OS_MEM_NODE_USED_FLAG             0x80000000
#define OS_MEM_NODE_ALIGNED_FLAG          0x40000000
#define OS_MEM_NODE_ALIGNED_AND_USED_FLAG (OS_MEM_NODE_USED_FLAG | OS_MEM_NODE_ALIGNED_FLAG)

#define OS_MEM_NODE_GET_ALIGNED_FLAG(sizeAndFlag) \
    ((sizeAndFlag) & OS_MEM_NODE_ALIGNED_FLAG)
#define OS_MEM_NODE_SET_ALIGNED_FLAG(sizeAndFlag) \
    ((sizeAndFlag) = ((sizeAndFlag) | OS_MEM_NODE_ALIGNED_FLAG))
#define OS_MEM_NODE_GET_ALIGNED_GAPSIZE(sizeAndFlag) \
    ((sizeAndFlag) & (~OS_MEM_NODE_ALIGNED_FLAG))
#define OS_MEM_NODE_GET_USED_FLAG(sizeAndFlag) \
    ((sizeAndFlag) & OS_MEM_NODE_USED_FLAG)
#define OS_MEM_NODE_SET_USED_FLAG(sizeAndFlag) \
    ((sizeAndFlag) = ((sizeAndFlag) | OS_MEM_NODE_USED_FLAG))
#define OS_MEM_NODE_GET_SIZE(sizeAndFlag) \
    ((sizeAndFlag) & (~OS_MEM_NODE_ALIGNED_AND_USED_FLAG))
#define OS_MEM_IS_NODE_NEXT_EXIST(node, poolInfo) \
    (((AARCHPTR)(node) + (node)->selfNode.sizeAndFlag) < ((AARCHPTR)(poolInfo) + (poolInfo)->poolSize))
#define OS_MEM_HEAD(pool, size) \
    OsDLnkHead(OS_MEM_HEAD_ADDR(pool), size)
#define OS_MEM_HEAD_ADDR(pool) \
    ((VOID *)((AARCHPTR)(pool) + sizeof(LosMemPoolInfo)))
#define OS_MEM_NEXT_NODE(node) \
    ((LosMemDynNode *)((UINT8 *)(node) + OS_MEM_NODE_GET_SIZE((node)->selfNode.sizeAndFlag)))
#define OS_MEM_FIRST_NODE(pool) \
    ((LosMemDynNode *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE))
#define OS_MEM_END_NODE(pool, size) \
    ((LosMemDynNode *)(((UINT8 *)(pool) + (size)) - OS_MEM_NODE_HEAD_SIZE))
#define OS_MEM_MIDDLE_ADDR_OPEN_END(startAddr, middleAddr, endAddr) \
    (((UINT8 *)(startAddr) <= ((UINT8 *)(middleAddr))) && (((UINT8 *)(middleAddr)) < ((UINT8 *)(endAddr))))
#define OS_MEM_MIDDLE_ADDR(startAddr, middleAddr, endAddr) \
    (((UINT8 *)(startAddr) <= ((UINT8 *)(middleAddr))) && (((UINT8 *)(middleAddr)) <= ((UINT8 *)(endAddr))))
#define OS_MEM_SET_MAGIC(value) \
    (value) = (LOS_DL_LIST *)((AARCHPTR)(&(value)) ^ (AARCHPTR)(-1))
#define OS_MEM_MAGIC_VALID(value) \
    ((((AARCHPTR)(value)) ^ ((AARCHPTR)(&(value)))) == (AARCHPTR)(-1))

UINT8 *m_aucSysMem0 = (UINT8 *)NULL;
UINT8 *m_aucSysMem1 = (UINT8 *)NULL;

UINT8 *m_aucSysNoCacheMem0 = (UINT8 *)NULL;
__attribute__((section(".data.init"))) AARCHPTR g_sys_mem_addr_end;
__attribute__((section(".data.init"))) AARCHPTR g_excInteractMemSize = 0;
#ifdef LOSCFG_BASE_MEM_NODE_SIZE_CHECK
static UINT8 g_memCheckLevel = (UINT8)LOS_MEM_CHECK_LEVEL_DEFAULT;
#endif

#ifdef LOSCFG_MEM_MUL_MODULE
UINT32 g_moduleMemUsedSize[MEM_MODULE_MAX + 1] = { 0 };
#endif

MALLOC_HOOK g_MALLOC_HOOK = (MALLOC_HOOK)NULL; /*lint !e611*/

#ifdef LOSCFG_MEM_HEAD_BACKUP
STATIC INLINE VOID OsMemDisctlNode(LosMemCtlNode *ctlNode)
{
    AARCHPTR checksum;

    checksum = (((AARCHPTR)ctlNode->freeNodeInfo.pstPrev) ^
                ((AARCHPTR)ctlNode->freeNodeInfo.pstNext) ^
                ((AARCHPTR)ctlNode->preNode) ^
                (UINT32)(ctlNode->gapSize) ^
                (UINT32)(ctlNode->sizeAndFlag) ^
                (UINT32)0xDEADBEEF);

    PRINT_ERR("node:%p checksum=%p[%p] freeNodeInfo.pstPrev=%p "
              "freeNodeInfo.pstNext=%p preNode=%p gapSize=0x%x sizeAndFlag=0x%x\n",
              ctlNode,
              ctlNode->checksum,
              checksum,
              ctlNode->freeNodeInfo.pstPrev,
              ctlNode->freeNodeInfo.pstNext,
              ctlNode->preNode,
              ctlNode->gapSize,
              ctlNode->sizeAndFlag);
}

STATIC INLINE VOID OsMemDispMoreDetails(LosMemDynNode *node)
{
    UINT32 taskID;
    LosTaskCB *taskCB = (LosTaskCB *)NULL;

    PRINT_ERR("************************************************\n");
    OsMemDisctlNode(&node->selfNode);
    PRINT_ERR("node's address: 0x%x\n", node);

    if (!OS_MEM_NODE_GET_USED_FLAG(node->selfNode.sizeAndFlag)) {
        PRINT_ERR("this is a FREE node\n");
        PRINT_ERR("************************************************\n\n");
        return;
    }

    taskID = OS_MEM_TASKID_GET(node);
    if (taskID >= g_taskMaxNum) {
        PRINT_ERR("The task [ID: 0x%x] is ILLEGAL\n", taskID);
        if (taskID == g_taskMaxNum) {
            PRINT_ERR("PROBABLY alloc by SYSTEM INIT, NOT IN ANY TASK\n");
        }
        PRINT_ERR("************************************************\n\n");
        return;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    if ((taskCB->taskStatus & OS_TASK_STATUS_UNUSED) ||
        (taskCB->taskEntry == NULL) ||
        (taskCB->taskName == NULL)) {
        PRINT_ERR("The task [ID: 0x%x] is NOT CREATED(ILLEGAL)\n", taskID);
        PRINT_ERR("************************************************\n\n");
        return;
    }

    PRINT_ERR("allocated by task: %s [ID = 0x%x]\n", taskCB->taskName, taskID);
#ifdef LOSCFG_MEM_MUL_MODULE
    PRINT_ERR("allocated by moduleID: %d\n", OS_MEM_MODID_GET(node));
#endif

    PRINT_ERR("************************************************\n\n");
}

STATIC INLINE VOID OsMemDispWildPointerMsg(LosMemDynNode *node, VOID *ptr)
{
    PRINT_ERR("*****************************************************\n");
    PRINT_ERR("find an control block at: %p, gap size: 0x%x, sizeof(LosMemDynNode): 0x%x\n", node,
              node->selfNode.gapSize, sizeof(LosMemDynNode));
    PRINT_ERR("the pointer should be: %p\n",
              (AARCHPTR)node + node->selfNode.gapSize + sizeof(LosMemDynNode));
    PRINT_ERR("the pointer given is: %p\n", ptr);
    PRINT_ERR("PROBABLY A WILD POINTER\n");
    osBackTrace();
    PRINT_ERR("*****************************************************\n\n");
}

STATIC INLINE VOID OsMemChecksumSet(LosMemCtlNode *ctlNode)
{
    ctlNode->checksum = (((AARCHPTR)ctlNode->freeNodeInfo.pstNext) ^
                         ((AARCHPTR)ctlNode->freeNodeInfo.pstPrev) ^
                         ((AARCHPTR)ctlNode->preNode) ^
                         (UINT32)(ctlNode->gapSize) ^
                         (UINT32)(ctlNode->sizeAndFlag) ^
                         (UINT32)0xDEADBEEF);
}

STATIC INLINE BOOL OsMemChecksumVerify(LosMemCtlNode *ctlNode)
{
    return ctlNode->checksum == (((AARCHPTR)ctlNode->freeNodeInfo.pstNext) ^
                                 ((AARCHPTR)ctlNode->freeNodeInfo.pstPrev) ^
                                 ((AARCHPTR)ctlNode->preNode) ^
                                 (UINT32)(ctlNode->gapSize) ^
                                 (UINT32)(ctlNode->sizeAndFlag) ^
                                 (UINT32)0xDEADBEEF);
}

STATIC INLINE VOID OsMemBackupSetup(LosMemDynNode *node)
{
    LosMemDynNode *nodePre = node->selfNode.preNode;

    if (nodePre != NULL) {
        nodePre->backupNode.freeNodeInfo.pstNext = node->selfNode.freeNodeInfo.pstNext;
        nodePre->backupNode.freeNodeInfo.pstPrev = node->selfNode.freeNodeInfo.pstPrev;
        nodePre->backupNode.preNode = node->selfNode.preNode;
        nodePre->backupNode.checksum = node->selfNode.checksum;
        nodePre->backupNode.gapSize = node->selfNode.gapSize;
#ifdef LOSCFG_MEM_RECORDINFO
        nodePre->backupNode.originSize = node->selfNode.originSize;
#endif
        nodePre->backupNode.sizeAndFlag = node->selfNode.sizeAndFlag;
    }
}

LosMemDynNode *OsMemNodeNextGet(VOID *pool, LosMemDynNode *node)
{
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;

    if (node == OS_MEM_END_NODE(pool, poolInfo->poolSize)) {
        return OS_MEM_FIRST_NODE(pool);
    } else {
        return OS_MEM_NEXT_NODE(node);
    }
}

STATIC INLINE UINT32 OsMemBackupSetup4Next(VOID *pool, LosMemDynNode *node)
{
    LosMemDynNode *nodeNext = OsMemNodeNextGet(pool, node);

    if (!OsMemChecksumVerify(&nodeNext->selfNode)) {
        PRINT_ERR("bad next node's selfNode in [%s]\n", __FUNCTION__);
        OsMemDisctlNode(&(nodeNext->selfNode));
        PRINT_ERR("preNode's details:\n");
        OsMemDispMoreDetails(node);

        return LOS_NOK;
    }

    if (!OsMemChecksumVerify(&node->backupNode)) {
        node->backupNode.freeNodeInfo.pstNext = nodeNext->selfNode.freeNodeInfo.pstNext;
        node->backupNode.freeNodeInfo.pstPrev = nodeNext->selfNode.freeNodeInfo.pstPrev;
        node->backupNode.preNode = nodeNext->selfNode.preNode;
        node->backupNode.checksum = nodeNext->selfNode.checksum;
        node->backupNode.gapSize = nodeNext->selfNode.gapSize;
#ifdef LOSCFG_MEM_RECORDINFO
        node->backupNode.originSize = nodeNext->selfNode.originSize;
#endif
        node->backupNode.sizeAndFlag = nodeNext->selfNode.sizeAndFlag;
    }
    return LOS_OK;
}

UINT32 OsMemBackupDoRestore(VOID *pool, LosMemDynNode *nodePre, LosMemDynNode *node)
{
    if (node == NULL || nodePre == NULL) {
        PRINT_ERR("node's address is NULL, node:0x%x, nodePre:0x%x\n", node, nodePre);
        return LOS_NOK;
    }
    PRINT_ERR("backup for this node:\n");
    OsMemDisctlNode(&nodePre->backupNode);
    PRINT_ERR("preNode's details:\n");
    OsMemDispMoreDetails(nodePre);

    node->selfNode.freeNodeInfo.pstNext = nodePre->backupNode.freeNodeInfo.pstNext;
    node->selfNode.freeNodeInfo.pstPrev = nodePre->backupNode.freeNodeInfo.pstPrev;
    node->selfNode.preNode = nodePre->backupNode.preNode;
    node->selfNode.checksum = nodePre->backupNode.checksum;
    node->selfNode.gapSize = nodePre->backupNode.gapSize;
#ifdef LOSCFG_MEM_RECORDINFO
    node->selfNode.originSize = nodePre->backupNode.originSize;
#endif
    node->selfNode.sizeAndFlag = nodePre->backupNode.sizeAndFlag;

    /* we should re-setup next node's backup on current node */
    return OsMemBackupSetup4Next(pool, node);
}

LosMemDynNode *osMemNodePrevGet(VOID *pool, LosMemDynNode *node)
{
    LosMemDynNode *nodeCur = NULL;
    LosMemDynNode *nodePre = NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;

    if (node == OS_MEM_FIRST_NODE(pool)) {
        nodePre = OS_MEM_END_NODE(pool, poolInfo->poolSize);
        if (!OsMemChecksumVerify(&(nodePre->selfNode))) {
            PRINT_ERR("current node is THE FIRST NODE!\n");
            PRINT_ERR("bad preNode's selfNode in [%s]\n", __FUNCTION__);
            OsMemDisctlNode(&(nodePre->selfNode));
            return nodePre;
        }
        if (!OsMemChecksumVerify(&(nodePre->backupNode))) {
            PRINT_ERR("current node is THE FIRST NODE!\n");
            PRINT_ERR("bad preNode's backupNode in [%s]\n", __FUNCTION__);
            OsMemDisctlNode(&(nodePre->backupNode));
            return nodePre;
        }
        return NULL;
    }

    for (nodeCur = OS_MEM_FIRST_NODE(pool);
         nodeCur < OS_MEM_END_NODE(pool, poolInfo->poolSize);
         nodeCur = OS_MEM_NEXT_NODE(nodeCur)) {
        if (!OsMemChecksumVerify(&(nodeCur->selfNode))) {
            PRINT_ERR("bad node's selfNode in [%s]\n", __FUNCTION__);
            OsMemDisctlNode(&(nodeCur->selfNode));

            if (nodePre == NULL) {
                return NULL;
            }

            PRINT_ERR("preNode's details:\n");
            OsMemDispMoreDetails(nodePre);

            /* due to the every step's checksum verify, nodePre is trustful */
            if (OsMemBackupDoRestore(pool, nodePre, nodeCur) != LOS_OK) {
                return NULL;
            }
        }

        if (!OsMemChecksumVerify(&(nodeCur->backupNode))) {
            PRINT_ERR("bad node's backupNode in [%s]\n", __FUNCTION__);
            OsMemDisctlNode(&(nodeCur->backupNode));

            if (nodePre != NULL) {
                PRINT_ERR("preNode's details:\n");
                OsMemDispMoreDetails(nodePre);
            }

            if (OsMemBackupSetup4Next(pool, nodeCur) != LOS_OK) {
                return NULL;
            }
        }

        if (OS_MEM_NEXT_NODE(nodeCur) == node) {
            return nodeCur;
        }

        if (OS_MEM_NEXT_NODE(nodeCur) > node) {
            break;
        }

        nodePre = nodeCur;
    }

    return NULL;
}

LosMemDynNode *OsMemNodePrevTryGet(VOID *pool, LosMemDynNode **node, VOID *ptr)
{
    UINT32 nodeShoudBe = 0;
    LosMemDynNode *nodeCur = NULL;
    LosMemDynNode *nodePre = NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;

    if (ptr == OS_MEM_FIRST_NODE(pool)) {
        nodePre = OS_MEM_END_NODE(pool, poolInfo->poolSize);
        if (!OsMemChecksumVerify(&(nodePre->selfNode))) {
            PRINT_ERR("current node is THE FIRST NODE!\n");
            PRINT_ERR("bad preNode's selfNode in [%s]\n", __FUNCTION__);
            OsMemDisctlNode(&(nodePre->selfNode));
            return nodePre;
        }
        if (!OsMemChecksumVerify(&(nodePre->backupNode))) {
            PRINT_ERR("current node is THE FIRST NODE!\n");
            PRINT_ERR("bad preNode's backupNode in [%s]\n", __FUNCTION__);
            OsMemDisctlNode(&(nodePre->backupNode));
            return nodePre;
        }
        return NULL;
    }

    for (nodeCur = OS_MEM_FIRST_NODE(pool);
         nodeCur < OS_MEM_END_NODE(pool, poolInfo->poolSize);
         nodeCur = OS_MEM_NEXT_NODE(nodeCur)) {
        if (!OsMemChecksumVerify(&(nodeCur->selfNode))) {
            PRINT_ERR("bad node's selfNode in [%s]\n", __FUNCTION__);
            OsMemDisctlNode(&(nodeCur->selfNode));

            if (nodePre == NULL) {
                return NULL;
            }

            PRINT_ERR("preNode's details:\n");
            OsMemDispMoreDetails(nodePre);

            /* due to the every step's checksum verify, nodePre is trustful */
            if (OsMemBackupDoRestore(pool, nodePre, nodeCur) != LOS_OK) {
                return NULL;
            }
        }

        if (!OsMemChecksumVerify(&(nodeCur->backupNode))) {
            PRINT_ERR("bad node's backupNode in [%s]\n", __FUNCTION__);
            OsMemDisctlNode(&(nodeCur->backupNode));

            if (nodePre != NULL) {
                PRINT_ERR("preNode's details:\n");
                OsMemDispMoreDetails(nodePre);
            }

            if (OsMemBackupSetup4Next(pool, nodeCur) != LOS_OK) {
                return NULL;
            }
        }

        nodeShoudBe = (AARCHPTR)nodeCur + nodeCur->selfNode.gapSize + sizeof(LosMemDynNode);
        if (nodeShoudBe == (AARCHPTR)ptr) {
            *node = nodeCur;
            return nodePre;
        }

        if (OS_MEM_NEXT_NODE(nodeCur) > (LosMemDynNode *)ptr) {
            OsMemDispWildPointerMsg(nodeCur, ptr);
            break;
        }

        nodePre = nodeCur;
    }

    return NULL;
}

STATIC INLINE UINT32 OsMemBackupTryRestore(VOID *pool, LosMemDynNode **node, VOID *ptr)
{
    LosMemDynNode *nodeHead = NULL;
    LosMemDynNode *nodePre = OsMemNodePrevTryGet(pool, &nodeHead, ptr);

    if (nodePre == NULL) {
        return LOS_NOK;
    }

    *node = nodeHead;
    return OsMemBackupDoRestore(pool, nodePre, *node);
}

STATIC INLINE UINT32 OsMemBackupRestore(VOID *pool, LosMemDynNode *node)
{
    LosMemDynNode *nodePre = osMemNodePrevGet(pool, node);

    if (nodePre == NULL) {
        return LOS_NOK;
    }

    return OsMemBackupDoRestore(pool, nodePre, node);
}

STATIC INLINE VOID OsMemSetGapSize(LosMemCtlNode *ctlNode, UINT32 gapSize)
{
    ctlNode->gapSize = gapSize;
}

static VOID OsMemNodeSave(LosMemDynNode *node)
{
    OsMemSetGapSize(&(node->selfNode), 0);
    OsMemChecksumSet(&(node->selfNode));
    OsMemBackupSetup(node);
}

static VOID OsMemNodeSaveWithGapSize(LosMemDynNode *node, UINT32 gapSize)
{
    OsMemSetGapSize(&(node->selfNode), gapSize);
    OsMemChecksumSet(&(node->selfNode));
    OsMemBackupSetup(node);
}

static VOID OsMemListDelete(LOS_DL_LIST *node, VOID *firstNode)
{
    LosMemDynNode *dynNode = NULL;

    node->pstNext->pstPrev = node->pstPrev;
    node->pstPrev->pstNext = node->pstNext;

    if ((VOID *)(node->pstNext) >= (VOID *)firstNode) {
        dynNode = LOS_DL_LIST_ENTRY(node->pstNext, LosMemDynNode, selfNode.freeNodeInfo);
        OsMemNodeSave(dynNode);
    }

    if ((VOID *)(node->pstPrev) >= (VOID *)firstNode) {
        dynNode = LOS_DL_LIST_ENTRY(node->pstPrev, LosMemDynNode, selfNode.freeNodeInfo);
        OsMemNodeSave(dynNode);
    }

    node->pstNext = (LOS_DL_LIST *)NULL;
    node->pstPrev = (LOS_DL_LIST *)NULL;

    dynNode = LOS_DL_LIST_ENTRY(node, LosMemDynNode, selfNode.freeNodeInfo);
    OsMemNodeSave(dynNode);
}

static VOID OsMemListAdd(LOS_DL_LIST *listNode, LOS_DL_LIST *node, VOID *firstNode)
{
    LosMemDynNode *dynNode = NULL;

    node->pstNext = listNode->pstNext;
    node->pstPrev = listNode;

    dynNode = LOS_DL_LIST_ENTRY(node, LosMemDynNode, selfNode.freeNodeInfo);
    OsMemNodeSave(dynNode);

    listNode->pstNext->pstPrev = node;
    if ((VOID *)(listNode->pstNext) >= firstNode) {
        dynNode = LOS_DL_LIST_ENTRY(listNode->pstNext, LosMemDynNode, selfNode.freeNodeInfo);
        OsMemNodeSave(dynNode);
    }

    listNode->pstNext = node;
}

VOID LOS_MemBadNodeShow(VOID *pool)
{
    LosMemDynNode *nodePre = (LosMemDynNode *)NULL;
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    UINTPTR intSave;

    if (pool == NULL) {
        return;
    }

    intSave = LOS_IntLock();

    for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= OS_MEM_END_NODE(pool, poolInfo->poolSize);
         tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        OsMemDisctlNode(&tmpNode->selfNode);

        if (OsMemChecksumVerify(&tmpNode->selfNode)) {
            continue;
        }

        nodePre = osMemNodePrevGet(pool, tmpNode);
        if (nodePre == NULL) {
            PRINT_ERR("current node is invalid, but cannot find preNode\n");
            continue;
        }

        PRINT_ERR("preNode's details:\n");
        OsMemDispMoreDetails(nodePre);
    }

    LOS_IntRestore(intSave);
    PRINTK("check finish\n");
}

#else  // without LOSCFG_MEM_HEAD_BACKUP

static VOID OsMemListDelete(LOS_DL_LIST *node, VOID *firstNode)
{
    node->pstNext->pstPrev = node->pstPrev;
    node->pstPrev->pstNext = node->pstNext;
    node->pstNext = (LOS_DL_LIST *)NULL;
    node->pstPrev = (LOS_DL_LIST *)NULL;
}

static VOID OsMemListAdd(LOS_DL_LIST *listNode, LOS_DL_LIST *node, VOID *firstNode)
{
    node->pstNext = listNode->pstNext;
    node->pstPrev = listNode;
    listNode->pstNext->pstPrev = node;
    listNode->pstNext = node;
}

#endif
#ifdef LOSCFG_EXC_INTERACTION
LITE_OS_SEC_TEXT_INIT UINT32 OsMemExcInteractionInit(AARCHPTR memStart)
{
    UINT32 ret;
    UINT32 poolSize;
    m_aucSysMem0 = (UINT8 *)((memStart + (POOL_ADDR_ALIGNSIZE - 1)) & ~((AARCHPTR)(POOL_ADDR_ALIGNSIZE - 1)));
    poolSize = OS_EXC_INTERACTMEM_SIZE;
    ret = LOS_MemInit(m_aucSysMem0, poolSize);
    PRINT_INFO("LiteOS kernel exc interaction memory address:%p,size:0x%x\n", m_aucSysMem0, poolSize);
    return ret;
}
#endif
LITE_OS_SEC_TEXT_INIT UINT32 OsMemSystemInit(AARCHPTR memStart)
{
    UINT32 ret;
    UINT32 poolSize;

    m_aucSysMem1 = (UINT8 *)((memStart + (POOL_ADDR_ALIGNSIZE - 1)) & ~((AARCHPTR)(POOL_ADDR_ALIGNSIZE - 1)));
    poolSize = OS_SYS_MEM_SIZE;
    ret = LOS_MemInit(m_aucSysMem1, poolSize);
    PRINT_INFO("LiteOS system heap memory address:%p,size:0x%x\n", m_aucSysMem1, poolSize);
#ifndef LOSCFG_EXC_INTERACTION
    m_aucSysMem0 = m_aucSysMem1;
#endif
    return ret;
}

#if OS_SYS_NOCACHEMEM_SIZE
UINT32 OsNocacheMemSystemInit(VOID)
{
    UINT32 ret;
    m_aucSysNoCacheMem0 = (g_sys_mem_addr_end - OS_SYS_NOCACHEMEM_SIZE);
    ret = LOS_MemInit(m_aucSysNoCacheMem0, OS_SYS_NOCACHEMEM_SIZE);
    return ret;
}
#endif

VOID OsMemInfoPrint(VOID *pool);
VOID *OsMemFindNodeCtrl(VOID *ptr);
#ifdef LOSCFG_MEM_LEAKCHECK
STATIC INLINE VOID OsMemLinkRegisterRecord(LosMemDynNode *node)
{
    UINT32 count = 0;
    UINT32 index = 0;
    AARCHPTR framePtr, tmpFramePtr, linkReg;

    (VOID)memset_s(node->selfNode.linkReg, (LOS_RECORD_LR_CNT * sizeof(AARCHPTR)), 0,
        (LOS_RECORD_LR_CNT * sizeof(AARCHPTR)));
    framePtr = Get_Fp();
    while ((framePtr > OS_SYS_FUNC_ADDR_START) && (framePtr < OS_SYS_FUNC_ADDR_END)) {
        tmpFramePtr = framePtr;
#ifdef __LP64__
        framePtr = *((AARCHPTR *)(framePtr));
        linkReg = *((AARCHPTR *)(tmpFramePtr + sizeof(AARCHPTR)));
#else
        linkReg = *((AARCHPTR *)(framePtr));
        framePtr = *((AARCHPTR *)(tmpFramePtr - sizeof(AARCHPTR)));
#endif
        if (index >= LOS_OMIT_LR_CNT) {
            node->selfNode.linkReg[count++] = linkReg;
            if (count == LOS_RECORD_LR_CNT) {
                break;
            }
        }
        index++;
    }
    return;
}
#endif

#define OS_CHECK_NULL(para)                               \
    do {                                                  \
        if ((para) == NULL) {                             \
            PRINT_ERR("%s %d\n", __FUNCTION__, __LINE__); \
            return;                                       \
        }                                                 \
    } while (0);

/*****************************************************************************
 Function : OsMemFindSuitableFreeBlock
 Description : find suitable free block use "best fit" algorithm
 Input       : pool    --- Pointer to memory pool
                 allocSize  --- Size of memory in bytes which note need allocate
 Output      : None
 Return      :NULL--no suitable block found
                 tmpNode--pointer a suitable free block
*****************************************************************************/
STATIC INLINE LosMemDynNode *OsMemFindSuitableFreeBlock(VOID *pool, UINT32 allocSize)
{
    LOS_DL_LIST *listNodeHead = (LOS_DL_LIST *)NULL;
    UINT32 maxCount = (((LosMemPoolInfo *)pool)->poolSize / allocSize) << 1;
    UINT32 count;

    for (listNodeHead = OS_MEM_HEAD(pool, allocSize); listNodeHead != NULL;
         listNodeHead = OsDLnkNextMultiHead(OS_MEM_HEAD_ADDR(pool), listNodeHead)) {
        LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
        count = 0;
        LOS_DL_LIST_FOR_EACH_ENTRY(tmpNode, listNodeHead, LosMemDynNode, selfNode.freeNodeInfo) /*lint !e413*/
        {
            if (count++ >= maxCount) {
                PRINT_ERR("[%s:%d]node: %p execute too much time\n", __FILE__, __LINE__, tmpNode);
                break;
            }

#ifdef LOSCFG_MEM_HEAD_BACKUP
            if (!OsMemChecksumVerify(&tmpNode->selfNode)) {
                PRINT_ERR("bad selfNode in [%s]\n", __FUNCTION__);
                OsMemDisctlNode(&tmpNode->selfNode);

                if (OsMemBackupRestore(pool, tmpNode) != LOS_OK) {
                    break;
                }
            }
#endif

            if ((AARCHPTR)tmpNode < (AARCHPTR)pool ||
                (AARCHPTR)tmpNode > ((AARCHPTR)pool + ((LosMemPoolInfo *)pool)->poolSize) ||
                ((AARCHPTR)tmpNode & (OS_MEM_ALIGN_SIZE - 1)) != 0) {
                PRINT_ERR("[%s:%d]Mem node data error:%p, allocSize=%d, tmpNode=%p\n",
                          __FUNCTION__, __LINE__, pool, allocSize, tmpNode);
                break;
            }
            if (tmpNode->selfNode.sizeAndFlag >= allocSize) {
                return tmpNode;
            }
        }
    }

    return (LosMemDynNode *)NULL;
}

/*****************************************************************************
 Function : OsMemClearNode
 Description : clear a mem Node , set every member to NULL
 Input       : node    --- Pointer to the mem node which will be cleared up
 Output      : None
 Return      : None
*****************************************************************************/
STATIC INLINE VOID OsMemClearNode(LosMemDynNode *node)
{
    (VOID)memset_s((VOID *)node, sizeof(LosMemDynNode), 0, sizeof(LosMemDynNode));
}

/*****************************************************************************
 Function : osMemMergeNode
 Description : merge this node and pre node ,then clear this node info
 Input       : node    --- Pointer to node which will be merged
 Output      : None
 Return      : None
*****************************************************************************/
STATIC INLINE VOID osMemMergeNode(LosMemDynNode *node)
{
    LosMemDynNode *nextNode = (LosMemDynNode *)NULL;

    (node->selfNode.preNode)->selfNode.sizeAndFlag += node->selfNode.sizeAndFlag;
    nextNode = (LosMemDynNode *)((AARCHPTR)node + node->selfNode.sizeAndFlag);
    nextNode->selfNode.preNode = node->selfNode.preNode;
#ifdef LOSCFG_MEM_HEAD_BACKUP
    OsMemNodeSave(node->selfNode.preNode);
    OsMemNodeSave(nextNode);
#endif
    OsMemClearNode(node);
}

/*****************************************************************************
 Function : osMemSpitNode
 Description : split new node from allocNode, and merge remainder mem if necessary
 Input       : pool --Pointer to memory pool
                  allocNode --the source node which new node be spit from to.
                                        After pick up it's node info, change to point the new node
                  allocSize -- the size of new node
 Output      : allocNode -- save new node addr
 Return      : None
*****************************************************************************/
STATIC INLINE VOID osMemSplitNode(VOID *pool,
                                  LosMemDynNode *allocNode, UINT32 allocSize)
{
    LosMemDynNode *newFreeNode = (LosMemDynNode *)NULL;
    LosMemDynNode *nextNode = (LosMemDynNode *)NULL;
    LOS_DL_LIST *listNodeHead = (LOS_DL_LIST *)NULL;
    VOID *firstNode = (VOID *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE);

    newFreeNode = (LosMemDynNode *)((UINT8 *)allocNode + allocSize);
    newFreeNode->selfNode.preNode = allocNode;
    newFreeNode->selfNode.sizeAndFlag = allocNode->selfNode.sizeAndFlag - allocSize;
    allocNode->selfNode.sizeAndFlag = allocSize;
    nextNode = OS_MEM_NEXT_NODE(newFreeNode);
    nextNode->selfNode.preNode = newFreeNode;
    if (!OS_MEM_NODE_GET_USED_FLAG(nextNode->selfNode.sizeAndFlag)) {
        OsMemListDelete(&(nextNode->selfNode.freeNodeInfo), firstNode);
        osMemMergeNode(nextNode);
    }
#ifdef LOSCFG_MEM_HEAD_BACKUP
    else {
        OsMemNodeSave(nextNode);
    }
#endif
    listNodeHead = OS_MEM_HEAD(pool, newFreeNode->selfNode.sizeAndFlag);
    OS_CHECK_NULL(listNodeHead);

    OsMemListAdd(listNodeHead, &(newFreeNode->selfNode.freeNodeInfo), firstNode);
#ifdef LOSCFG_MEM_HEAD_BACKUP
    OsMemNodeSave(newFreeNode);
#endif
}

/*****************************************************************************
 Function : osMemFreeNode
 Description : free the node from memory & if there are free node beside, merger them.
                    at last update "listNodeHead' which saved all free node control head
 Input       : node -- the node which need be freed
                  pool --Pointer to memory pool
 Output      : None
 Return      : None
*****************************************************************************/
STATIC INLINE VOID osMemFreeNode(LosMemDynNode *node, VOID *pool)
{
    LosMemDynNode *nextNode = (LosMemDynNode *)NULL;
    LOS_DL_LIST *listNodeHead = (LOS_DL_LIST *)NULL;
    VOID *firstNode = (VOID *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE);

#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    poolInfo->poolCurUsedSize -= OS_MEM_NODE_GET_SIZE(node->selfNode.sizeAndFlag);
#endif
    if (pool == (VOID *)OS_SYS_MEM_ADDR || pool == (VOID *)m_aucSysMem0) {
        OS_MEM_REDUCE_USED(OS_MEM_NODE_GET_SIZE(node->selfNode.sizeAndFlag), OS_MEM_TASKID_GET(node));
    }

    node->selfNode.sizeAndFlag = OS_MEM_NODE_GET_SIZE(node->selfNode.sizeAndFlag);
#ifdef LOSCFG_MEM_HEAD_BACKUP
    OsMemNodeSave(node);
#endif
#ifdef LOSCFG_MEM_LEAKCHECK
    OsMemLinkRegisterRecord(node);
#endif
    if ((node->selfNode.preNode != NULL) &&
        (!OS_MEM_NODE_GET_USED_FLAG((node->selfNode.preNode)->selfNode.sizeAndFlag))) {
        LosMemDynNode *preNode = node->selfNode.preNode;
        osMemMergeNode(node);
        nextNode = OS_MEM_NEXT_NODE(preNode);
        if (!OS_MEM_NODE_GET_USED_FLAG(nextNode->selfNode.sizeAndFlag)) {
            OsMemListDelete(&(nextNode->selfNode.freeNodeInfo), firstNode);
            osMemMergeNode(nextNode);
        }

        OsMemListDelete(&(preNode->selfNode.freeNodeInfo), firstNode);
        listNodeHead = OS_MEM_HEAD(pool, preNode->selfNode.sizeAndFlag);
        OS_CHECK_NULL(listNodeHead);

        OsMemListAdd(listNodeHead, &(preNode->selfNode.freeNodeInfo), firstNode);
    } else {
        nextNode = OS_MEM_NEXT_NODE(node);
        if (!OS_MEM_NODE_GET_USED_FLAG(nextNode->selfNode.sizeAndFlag)) {
            OsMemListDelete(&(nextNode->selfNode.freeNodeInfo), firstNode);
            osMemMergeNode(nextNode);
        }

        listNodeHead = OS_MEM_HEAD(pool, node->selfNode.sizeAndFlag);
        OS_CHECK_NULL(listNodeHead);

        OsMemListAdd(listNodeHead, &(node->selfNode.freeNodeInfo), firstNode);
    }
}

/*****************************************************************************
 Function : OsMemCheckUsedNode
 Description : check the result if pointer memory node belongs to pointer memory pool
 Input       : pool --Pointer to memory pool
                  node -- the node which need be checked
 Output      : None
 Return      : LOS_OK or LOS_NOK
*****************************************************************************/
#ifdef LOS_DLNK_SAFE_CHECK
STATIC INLINE UINT32 OsMemCheckUsedNode(VOID *pool, LosMemDynNode *node)
{
    LosMemDynNode *tmpNode = NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    LosMemDynNode *endNode = OS_MEM_END_NODE(pool, poolInfo->poolSize);

    for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode < endNode; tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        if ((tmpNode == node) &&
            OS_MEM_NODE_GET_USED_FLAG(tmpNode->selfNode.sizeAndFlag)) {
            return LOS_OK;
        } else if (tmpNode > node) {
            return LOS_NOK;
        }
    }

    return LOS_NOK;
}

#elif defined(LOS_DLNK_SIMPLE_CHECK)
STATIC INLINE UINT32 OsMemCheckUsedNode(VOID *pool, LosMemDynNode *node)
{
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    LosMemDynNode *startNode = OS_MEM_FIRST_NODE(pool);
    LosMemDynNode *endNode = OS_MEM_END_NODE(pool, poolInfo->poolSize);
    if (!OS_MEM_MIDDLE_ADDR_OPEN_END(startNode, node, endNode)) {
        return LOS_NOK;
    }

    if (!OS_MEM_NODE_GET_USED_FLAG(node->selfNode.sizeAndFlag)) {
        return LOS_NOK;
    }

    if ((!OS_MEM_MAGIC_VALID(node->selfNode.freeNodeInfo.pstPrev))) {
        return LOS_NOK;
    }

    return LOS_OK;
}

#else
STATIC INLINE BOOL OsMemIsNodeValid(const LosMemDynNode *node, const LosMemDynNode *startNode,
                                    const LosMemDynNode *endNode,
                                    const UINT8 *startPool, const UINT8 *endPool)
{
    if (!OS_MEM_MIDDLE_ADDR(startNode, node, endNode)) {
        return FALSE;
    }

    if (OS_MEM_NODE_GET_USED_FLAG(node->selfNode.sizeAndFlag)) {
        if ((!OS_MEM_MAGIC_VALID(node->selfNode.freeNodeInfo.pstPrev))) {
            return FALSE;
        }
        return TRUE;
    }

    if ((!OS_MEM_MIDDLE_ADDR_OPEN_END(startPool, node->selfNode.freeNodeInfo.pstPrev, endPool))) {
        return FALSE;
    }

    return TRUE;
}

STATIC INLINE UINT32 OsMemCheckUsedNode(VOID *pool, LosMemDynNode *node)
{
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    LosMemDynNode *startNode = OS_MEM_FIRST_NODE(pool);
    LosMemDynNode *endNode = OS_MEM_END_NODE(pool, poolInfo->poolSize);
    UINT8 *endPool = (UINT8 *)pool + poolInfo->poolSize;
    const LosMemDynNode *nextNode = (const LosMemDynNode *)NULL;
    if (!OsMemIsNodeValid(node, startNode, endNode, (UINT8 *)pool, endPool)) {
        return LOS_NOK;
    }

    if (!OS_MEM_NODE_GET_USED_FLAG(node->selfNode.sizeAndFlag)) {
        return LOS_NOK;
    }

    nextNode = OS_MEM_NEXT_NODE(node);
    if (!OsMemIsNodeValid(nextNode, startNode, endNode, (UINT8 *)pool, endPool)) {
        return LOS_NOK;
    }

    if (nextNode->selfNode.preNode != node) {
        return LOS_NOK;
    }

    if (node != startNode) {
        if (!OsMemIsNodeValid(node->selfNode.preNode, startNode, endNode, (UINT8 *)pool, endPool)) {
            return LOS_NOK;
        }

        if (OS_MEM_NEXT_NODE(node->selfNode.preNode) != node) {
            return LOS_NOK;
        }
    }

    return LOS_OK;
}

#endif

/*****************************************************************************
 Function : OsMemSetMagicNumAndTaskID
 Description : set magic & taskid
 Input       : node -- the node which will be set magic &  taskid
 Output      : None
 Return      : None
*****************************************************************************/
STATIC INLINE VOID OsMemSetMagicNumAndTaskID(LosMemDynNode *node)
{
    OS_MEM_SET_MAGIC(node->selfNode.freeNodeInfo.pstPrev);

    /* If the operation occured before task initialization(g_losTask.runTask was not assigned)
       or in interrupt,make the value of taskid of node to oxffffffff */
    if (g_losTask.runTask != NULL && OS_INT_INACTIVE) {
        OS_MEM_TASKID_SET(node, g_losTask.runTask->taskID);
    } else {
        /* If the task mode does not initialize, the field is the 0xffffffff */
        node->selfNode.freeNodeInfo.pstNext = (LOS_DL_LIST *)OS_NULL_INT;
        /* TODO: the commend task-MEMUSE is not include system initialization malloc */
    }
}
LITE_OS_SEC_TEXT_MINOR static inline UINT32 OsMemPoolDlinkcheck(LosMemPoolInfo *pool, LOS_DL_LIST listHead)
{
    if (((AARCHPTR)(listHead.pstPrev) < (AARCHPTR)(pool + 1)) ||
        ((AARCHPTR)(listHead.pstPrev) >= ((AARCHPTR)pool + pool->poolSize))) {
        return LOS_NOK;
    }

    if (((AARCHPTR)(listHead.pstNext) < (AARCHPTR)(pool + 1)) ||
        ((AARCHPTR)(listHead.pstNext) >= ((AARCHPTR)pool + pool->poolSize))) {
        return LOS_NOK;
    }

    return LOS_OK;
}
/*****************************************************************************
 Function : OsMemPoolHeadInfoPrint
 Description : show mem pool header info
 Input       : pool --Pointer to memory pool
 Output      : None
 Return      : None
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID OsMemPoolHeadInfoPrint(VOID *pool)
{
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    UINT32 dlinkNum = 0;
    UINT32 flag = 0;
    LosMultipleDlinkHead *dlinkHead = (LosMultipleDlinkHead *)NULL;

    if ((poolInfo == NULL) || (IS_ALIGNED(poolInfo, sizeof(VOID *)) == 0)) {
#ifdef LOSCFG_SHELL_EXCINFO
        WriteExcInfoToBuf("wrong mem pool addr: %p, func:%s,line:%d\n", poolInfo, __FUNCTION__, __LINE__);
#endif
        PRINT_ERR("wrong mem pool addr: %p, func:%s,line:%d\n", poolInfo, __FUNCTION__, __LINE__);
        return;
    }

    dlinkHead = (LosMultipleDlinkHead *)(poolInfo + 1);
    for (dlinkNum = 0; dlinkNum < OS_MULTI_DLNK_NUM; dlinkNum++) {
        if (OsMemPoolDlinkcheck(pool, dlinkHead->listHead[dlinkNum])) {
            flag = 1;
            PRINT_ERR("DlinkHead[%d]: pstPrev:0x%x, pstNext:0x%x\n",
                      dlinkNum, dlinkHead->listHead[dlinkNum].pstPrev, dlinkHead->listHead[dlinkNum].pstNext);
#ifdef LOSCFG_SHELL_EXCINFO
            WriteExcInfoToBuf("DlinkHead[%d]: pstPrev:0x%x, pstNext:0x%x\n",
                              dlinkNum, dlinkHead->listHead[dlinkNum].pstPrev, dlinkHead->listHead[dlinkNum].pstNext);
#endif
        }
    }
    if (flag) {
        PRINTK("mem pool info: poolAddr:%p, poolSize:0x%x\n", poolInfo->pool, poolInfo->poolSize);
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
        PRINTK("mem pool info: poolWaterLine:0x%x, poolCurUsedSize:0x%x\n", poolInfo->poolWaterLine,
               poolInfo->poolCurUsedSize);
#endif

#ifdef LOSCFG_SHELL_EXCINFO
        WriteExcInfoToBuf("mem pool info: poolAddr:%p, poolSize:0x%x\n", poolInfo->pool, poolInfo->poolSize);
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
        WriteExcInfoToBuf("mem pool info: poolWaterLine:0x%x, poolCurUsedSize:0x%x\n",
                          poolInfo->poolWaterLine, poolInfo->poolCurUsedSize);
#endif
#endif
    }

    return;
}
/*****************************************************************************
 Function : LOS_MemIntegrityCheck
 Description : memory pool integrity checking
 Input       : pool --Pointer to memory pool
 Output      : None
 Return      : LOS_OK --memory pool integrate  or LOS_NOK--memory pool impaired
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemIntegrityCheck(VOID *pool)
{
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    LosMemDynNode *preNode = (LosMemDynNode *)NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    UINT8 *endPool = (UINT8 *)NULL;
    LosTaskCB *taskCB = (LosTaskCB *)NULL;
    UINT32 taskID;
    UINTPTR intSave;

    if (pool == NULL) {
        return LOS_NOK;
    }

    endPool = (UINT8 *)pool + poolInfo->poolSize;

    intSave = LOS_IntLock();

    OsMemPoolHeadInfoPrint(pool);

    preNode = OS_MEM_FIRST_NODE(pool);
    for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode < OS_MEM_END_NODE(pool, poolInfo->poolSize);
         tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        if (OS_MEM_NODE_GET_USED_FLAG(tmpNode->selfNode.sizeAndFlag)) {
            if (!OS_MEM_MAGIC_VALID(tmpNode->selfNode.freeNodeInfo.pstPrev)) {
                PRINT_ERR("[%s], %d, memory check error!\n"
                          "memory used but magic num wrong, freeNodeInfo.pstPrev(magic num):%p \n",
                          __FUNCTION__, __LINE__, tmpNode->selfNode.freeNodeInfo.pstPrev);
#ifdef LOSCFG_SHELL_EXCINFO
                WriteExcInfoToBuf("[%s], %d, memory check error!\n"
                                  "memory used but magic num wrong, freeNodeInfo.pstPrev(magic num):0x%x \n",
                                  __FUNCTION__, __LINE__, tmpNode->selfNode.freeNodeInfo.pstPrev);
#endif
                goto errout;
            }
        } else {  // is free node, check free node range
            if (!OS_MEM_MIDDLE_ADDR_OPEN_END(pool, tmpNode->selfNode.freeNodeInfo.pstPrev, endPool)) {
                PRINT_ERR("[%s], %d, memory check error!\n"
                          "freeNodeInfo.pstPrev:%p is out of legal mem range[%p, %p]\n",
                          __FUNCTION__, __LINE__, tmpNode->selfNode.freeNodeInfo.pstPrev, pool, endPool);
#ifdef LOSCFG_SHELL_EXCINFO
                WriteExcInfoToBuf("[%s], %d, memory check error!\n"
                                  "freeNodeInfo.pstPrev:0x%x is out of legal mem range[0x%x, 0x%x]\n",
                                  __FUNCTION__, __LINE__, tmpNode->selfNode.freeNodeInfo.pstPrev, pool, endPool);
#endif
                goto errout;
            }
            if (!OS_MEM_MIDDLE_ADDR_OPEN_END(pool, tmpNode->selfNode.freeNodeInfo.pstNext, endPool)) {
                PRINT_ERR("[%s], %d, memory check error!\n"
                          "freeNodeInfo.pstNext:%p is out of legal mem range[%p, %p]\n",
                          __FUNCTION__, __LINE__, tmpNode->selfNode.freeNodeInfo.pstNext, pool, endPool);
#ifdef LOSCFG_SHELL_EXCINFO
                WriteExcInfoToBuf("[%s], %d, memory check error!\n"
                                  "freeNodeInfo.pstNext:0x%x is out of legal mem range[0x%x, 0x%x]\n",
                                  __FUNCTION__, __LINE__, tmpNode->selfNode.freeNodeInfo.pstNext, pool, endPool);
#endif
                goto errout;
            }
        }

        preNode = tmpNode;
    }
    LOS_IntRestore(intSave);
    return LOS_OK;

errout:
    PRINTK("\n broken node head: %p  %p  %p  0x%x, pre node head: %p  %p  %p  0x%x\n",
           tmpNode->selfNode.freeNodeInfo.pstPrev, tmpNode->selfNode.freeNodeInfo.pstNext,
           tmpNode->selfNode.preNode, tmpNode->selfNode.sizeAndFlag,
           preNode->selfNode.freeNodeInfo.pstPrev, preNode->selfNode.freeNodeInfo.pstNext,
           preNode->selfNode.preNode, preNode->selfNode.sizeAndFlag);
#ifdef LOSCFG_SHELL_EXCINFO
    WriteExcInfoToBuf("\n broken node head: %p  %p  %p  0x%x, pre node head: %p  %p  %p  0x%x\n",
                      tmpNode->selfNode.freeNodeInfo.pstPrev, tmpNode->selfNode.freeNodeInfo.pstNext,
                      tmpNode->selfNode.preNode, tmpNode->selfNode.sizeAndFlag,
                      preNode->selfNode.freeNodeInfo.pstPrev, preNode->selfNode.freeNodeInfo.pstNext,
                      preNode->selfNode.preNode, preNode->selfNode.sizeAndFlag);
#endif
    PRINTK("\n---------------------------------------------\n");
    PRINTK("dump mem tmpNode:0x%x ~ 0x%x\n", tmpNode, ((AARCHPTR)tmpNode + NODEDUMPSIZE));
    (VOID)OsDumpMemByte(NODEDUMPSIZE, (AARCHPTR)tmpNode);
    PRINTK("\n---------------------------------------------\n");
    if (preNode != tmpNode) {
        PRINTK("dump mem :0x%x ~ tmpNode:0x%x\n", ((AARCHPTR)tmpNode - NODEDUMPSIZE), tmpNode);
        (VOID)OsDumpMemByte(NODEDUMPSIZE, ((AARCHPTR)tmpNode - NODEDUMPSIZE));
        PRINTK("\n---------------------------------------------\n");
    }
    LOS_IntRestore(intSave);
    taskID = OS_MEM_TASKID_GET(preNode);
    if (taskID >= g_taskMaxNum) {
#ifdef LOSCFG_SHELL_EXCINFO
        WriteExcInfoToBuf("Task ID %d in pre node is invalid!\n", taskID);
#endif
        LOS_Panic("Task ID %d in pre node is invalid!\n", taskID);
        return LOS_NOK;
    }
    taskCB = OS_TCB_FROM_TID(taskID);

    if ((taskCB->taskStatus & OS_TASK_STATUS_UNUSED) ||
        (taskCB->taskEntry == NULL) ||
        (taskCB->taskName == NULL)) {
#ifdef LOSCFG_SHELL_EXCINFO
        WriteExcInfoToBuf("\r\nTask ID %d in pre node is not created or deleted!\n", taskID);
#endif
        LOS_Panic("\r\nTask ID %d in pre node is not created!\n", taskID);
        return LOS_NOK;
    }
#ifdef LOSCFG_SHELL_EXCINFO
    WriteExcInfoToBuf("cur node: %p\npre node: %p\npre node was allocated by task:%s\n",
                      tmpNode, preNode, taskCB->taskName); /*lint !e515*/
#endif
    LOS_Panic("cur node: %p\n"
              "pre node: %p\n"
              "pre node was allocated by task:%s\n",
              tmpNode, preNode, taskCB->taskName); /*lint !e515*/
    return LOS_NOK;
}

/*****************************************************************************
 Function : OsMemAllocWithCheck
 Description : Allocate node from Memory pool
 Input       : pool    --- Pointer to memory pool
                 size  --- Size of memory in bytes to allocate
 Output      : None
 Return      : Pointer to allocated memory
*****************************************************************************/
STATIC INLINE VOID *OsMemAllocWithCheck(VOID *pool, UINT32 size)
{
    LosMemDynNode *allocNode = (LosMemDynNode *)NULL;
    UINT32 allocSize;
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
#endif
    VOID *firstNode = (VOID *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE);

    if (g_MALLOC_HOOK != NULL) {
        g_MALLOC_HOOK();
    }

#ifdef LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK
    (VOID)LOS_MemIntegrityCheck(pool);
#endif

    allocSize = OS_MEM_ALIGN(size + OS_MEM_NODE_HEAD_SIZE, OS_MEM_ALIGN_SIZE);
    allocNode = OsMemFindSuitableFreeBlock(pool, allocSize);
    if (allocNode == NULL) {
        PRINT_ERR("---------------------------------------------------"
                  "--------------------------------------------------------\n");
        OsMemInfoPrint(pool);
        PRINT_ERR("[%s] No suitable free block, require free node size: 0x%x\n", __FUNCTION__, allocSize);
        PRINT_ERR("----------------------------------------------------"
                  "-------------------------------------------------------\n");
        return NULL;
    }
    if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_ALIGN_SIZE) <= allocNode->selfNode.sizeAndFlag) {
        osMemSplitNode(pool, allocNode, allocSize);
    }
    OsMemListDelete(&(allocNode->selfNode.freeNodeInfo), firstNode);
    OsMemSetMagicNumAndTaskID(allocNode);
    OS_MEM_NODE_SET_USED_FLAG(allocNode->selfNode.sizeAndFlag);
    if (pool == (VOID *)OS_SYS_MEM_ADDR || pool == (VOID *)m_aucSysMem0) {
        OS_MEM_ADD_USED(OS_MEM_NODE_GET_SIZE(allocNode->selfNode.sizeAndFlag), OS_MEM_TASKID_GET(allocNode));
    }
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    poolInfo->poolCurUsedSize += OS_MEM_NODE_GET_SIZE(allocNode->selfNode.sizeAndFlag);
    if (poolInfo->poolCurUsedSize > poolInfo->poolWaterLine) {
        poolInfo->poolWaterLine = poolInfo->poolCurUsedSize;
    }
#endif
#ifdef LOSCFG_MEM_RECORDINFO
    allocNode->selfNode.originSize = size;
#endif

#ifdef LOSCFG_MEM_HEAD_BACKUP
    OsMemNodeSave(allocNode);
#endif

#ifdef LOSCFG_MEM_LEAKCHECK
    OsMemLinkRegisterRecord(allocNode);
#endif
    return (allocNode + 1);
}

/*****************************************************************************
 Function : osMemReAllocSmaller
 Description : reAlloc a smaller memory node
 Input       : pool    --- Pointer to memory pool
                 allocSize  --- the size of new node which will be alloced
                 node --the node which wille be realloced
                 nodeSize -- the size of old node
 Output      : node -- pointer to the new node after realloc
 Return      : None
*****************************************************************************/
STATIC INLINE VOID osMemReAllocSmaller(VOID *pool, UINT32 allocSize, LosMemDynNode *node, UINT32 nodeSize)
{
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
#endif
    if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_ALIGN_SIZE) <= nodeSize) {
        node->selfNode.sizeAndFlag = nodeSize;
        osMemSplitNode(pool, node, allocSize);
        OS_MEM_NODE_SET_USED_FLAG(node->selfNode.sizeAndFlag);
#ifdef LOSCFG_MEM_HEAD_BACKUP
        OsMemNodeSave(node);
#endif
        if (pool == (VOID *)OS_SYS_MEM_ADDR || pool == (VOID *)m_aucSysMem0) {
            OS_MEM_REDUCE_USED(nodeSize - allocSize, OS_MEM_TASKID_GET(node));
        }
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
        poolInfo->poolCurUsedSize -= (nodeSize - allocSize);
#endif
    }
#ifdef LOSCFG_MEM_LEAKCHECK
    OsMemLinkRegisterRecord(node);
#endif
}

/*****************************************************************************
 Function : OsMemMergeNodeForReAllocBigger
 Description : reAlloc a Bigger memory node after merge node and nextNode
 Input       : pool    --- Pointer to memory pool
                 allocSize  --- the size of new node which will be alloced
                 node --the node which wille be realloced
                 nodeSize -- the size of old node
                 nextNode -- pointer next node which will be merged
 Output      : node -- pointer to the new node after realloc
 Return      : None
*****************************************************************************/
STATIC INLINE VOID OsMemMergeNodeForReAllocBigger(VOID *pool, UINT32 allocSize, LosMemDynNode *node,
                                                  UINT32 nodeSize, LosMemDynNode *nextNode)
{
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
#endif
    VOID *firstNode = (VOID *)((UINT8 *)OS_MEM_HEAD_ADDR(pool) + OS_DLNK_HEAD_SIZE);

    node->selfNode.sizeAndFlag = nodeSize;
    OsMemListDelete(&(nextNode->selfNode.freeNodeInfo), firstNode);
    osMemMergeNode(nextNode);
    if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_ALIGN_SIZE) <= node->selfNode.sizeAndFlag) {
        osMemSplitNode(pool, node, allocSize);
    }
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    poolInfo->poolCurUsedSize += (node->selfNode.sizeAndFlag - nodeSize);
    if (poolInfo->poolCurUsedSize > poolInfo->poolWaterLine) {
        poolInfo->poolWaterLine = poolInfo->poolCurUsedSize;
    }
#endif
    if (pool == (VOID *)OS_SYS_MEM_ADDR || pool == (VOID *)m_aucSysMem0) {
        OS_MEM_ADD_USED(node->selfNode.sizeAndFlag - nodeSize, OS_MEM_TASKID_GET(node));
    }
    OS_MEM_NODE_SET_USED_FLAG(node->selfNode.sizeAndFlag);
#ifdef LOSCFG_MEM_HEAD_BACKUP
    OsMemNodeSave(node);
#endif
#ifdef LOSCFG_MEM_LEAKCHECK
    OsMemLinkRegisterRecord(node);
#endif
}

/*****************************************************************************
 Function : LOS_MemInit
 Description : Initialize Dynamic Memory pool
 Input       : pool    --- Pointer to memory pool
                 size  --- Size of memory in bytes to allocate
 Output      : None
 Return      : LOS_OK - Ok, OS_ERROR - Error
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemInit(VOID *pool, UINT32 size)
{
    LosMemDynNode *newNode = (LosMemDynNode *)NULL;
    LosMemDynNode *endNode = (LosMemDynNode *)NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)NULL;
    UINTPTR intSave;
    LOS_DL_LIST *listNodeHead = (LOS_DL_LIST *)NULL;
#ifdef LOSCFG_MEM_MUL_POOL
    VOID *nextPool = g_poolHead;
    VOID *curPool = g_poolHead;
    AARCHPTR poolEnd;
#endif

    if ((pool == NULL) || (size < (OS_MEM_MIN_POOL_SIZE))) {
        return OS_ERROR;
    }

    if (!IS_ALIGNED(size, OS_MEM_ALIGN_SIZE)) {
        PRINT_WARN("pool [%p, %p) size 0x%x sholud be aligned with OS_MEM_ALIGN_SIZE\n",
                   pool, (AARCHPTR)pool + size, size);
        size = OS_MEM_ALIGN(size, OS_MEM_ALIGN_SIZE) - OS_MEM_ALIGN_SIZE;
    }
#ifdef LOSCFG_MEM_MUL_POOL
    while (nextPool != NULL) {
        poolEnd = (AARCHPTR)nextPool + LOS_MemPoolSizeGet(nextPool);
        if ((pool <= nextPool && ((AARCHPTR)pool + size) > (AARCHPTR)nextPool) ||
            ((AARCHPTR)pool < poolEnd && ((AARCHPTR)pool + size) >= poolEnd)) {
            PRINT_ERR("pool [%p, %p) conflict with pool [%p, %p)\n",
                      pool, (AARCHPTR)pool + size,
                      nextPool, (AARCHPTR)nextPool + LOS_MemPoolSizeGet(nextPool));
            return OS_ERROR;
        }
        curPool = nextPool;
        nextPool = ((LosMemPoolInfo *)nextPool)->nextPool;
    }
#endif

    intSave = LOS_IntLock();

    poolInfo = (LosMemPoolInfo *)pool;
    poolInfo->pool = pool;
    poolInfo->poolSize = size;
    OsDLnkInitMultiHead(OS_MEM_HEAD_ADDR(pool));
    newNode = OS_MEM_FIRST_NODE(pool);
    newNode->selfNode.sizeAndFlag = ((size - ((AARCHPTR)newNode - (AARCHPTR)pool)) - OS_MEM_NODE_HEAD_SIZE);
    newNode->selfNode.preNode = (LosMemDynNode *)OS_MEM_END_NODE(pool, size);
    listNodeHead = OS_MEM_HEAD(pool, newNode->selfNode.sizeAndFlag);
    if (listNodeHead == NULL) {
        LOS_IntRestore(intSave);
        return OS_ERROR;
    }

    LOS_ListTailInsert(listNodeHead, &(newNode->selfNode.freeNodeInfo));
    endNode = (LosMemDynNode *)OS_MEM_END_NODE(pool, size);
    (VOID)memset_s(endNode, sizeof(*endNode), 0, sizeof(*endNode));
    endNode->selfNode.preNode = newNode;
    endNode->selfNode.sizeAndFlag = OS_MEM_NODE_HEAD_SIZE;
    OS_MEM_NODE_SET_USED_FLAG(endNode->selfNode.sizeAndFlag);
    OsMemSetMagicNumAndTaskID(endNode);
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    poolInfo->poolCurUsedSize = sizeof(LosMemPoolInfo) + OS_MULTI_DLNK_HEAD_SIZE +
                                OS_MEM_NODE_GET_SIZE(endNode->selfNode.sizeAndFlag);
    poolInfo->poolWaterLine = poolInfo->poolCurUsedSize;
#endif
#ifdef LOSCFG_MEM_HEAD_BACKUP
    OsMemNodeSave(newNode);
    OsMemNodeSave(endNode);
#endif
#ifdef LOSCFG_MEM_MUL_POOL
    if (g_poolHead == NULL) {
        g_poolHead = pool;
    } else {
        ((LosMemPoolInfo *)curPool)->nextPool = pool;
    }

    ((LosMemPoolInfo *)pool)->nextPool = NULL;
#endif

    LOS_IntRestore(intSave);

    return LOS_OK;
}

#ifdef LOSCFG_MEM_MUL_POOL
LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemDeInit(VOID *pool)
{
    UINTPTR intSave;
    UINT32 ret = LOS_NOK;
    VOID *nextPool, *curPool;

    intSave = LOS_IntLock();
    do {
        if (pool == NULL) {
            break;
        }

        if (pool == g_poolHead) {
            g_poolHead = ((LosMemPoolInfo *)g_poolHead)->nextPool;
            ret = LOS_OK;
            break;
        }

        curPool = g_poolHead;
        nextPool = g_poolHead;

        while (nextPool != NULL) {
            if (pool == nextPool) {
                ((LosMemPoolInfo *)curPool)->nextPool = ((LosMemPoolInfo *)nextPool)->nextPool;
                ret = LOS_OK;
                break;
            }
            curPool = nextPool;
            nextPool = ((LosMemPoolInfo *)nextPool)->nextPool;
        }
    } while (0);

    LOS_IntRestore(intSave);
    return ret;
}

LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemPoolList(VOID)
{
    VOID *nextPool = g_poolHead;
    UINT32 index = 0;
    while (nextPool != NULL) {
        PRINTK("pool%d :\n", index++);
        OsMemInfoPrint(nextPool);
        nextPool = ((LosMemPoolInfo *)nextPool)->nextPool;
    }
    return index;
}
#endif

/*****************************************************************************
 Function : LOS_MemAlloc
 Description : Allocate node from Memory pool
 Input       : pool    --- Pointer to memory pool
                 size  --- Size of memory in bytes to allocate
 Output      : None
 Return      : Pointer to allocated memory node
*****************************************************************************/
LITE_OS_SEC_TEXT VOID *LOS_MemAlloc(VOID *pool, UINT32 size)
{
    VOID *ptr = NULL;
    UINTPTR intSave = LOS_IntLock();

    do {
        if ((pool == NULL) || (size == 0)) {
            break;
        }

        if (OS_MEM_NODE_GET_USED_FLAG(size) || OS_MEM_NODE_GET_ALIGNED_FLAG(size)) {
            break;
        }

        ptr = OsMemAllocWithCheck(pool, size);

    } while (0);
#ifdef LOSCFG_MEM_RECORDINFO
    OsMemRecordMalloc(ptr, size);
#endif
    LOS_IntRestore(intSave);
    return ptr;
}

/*****************************************************************************
 Function : LOS_MemAllocAlign
 Description : align size then allocate node from Memory pool
 Input       : pool    --- Pointer to memory pool
                 size  --- Size of memory in bytes to allocate
                 boundary -- align form
 Output      : None
 Return      : Pointer to allocated memory node
*****************************************************************************/
LITE_OS_SEC_TEXT VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary)
{
    UINT32 useSize = 0;
    UINT32 gapSize = 0;
    VOID *ptr = NULL;
    VOID *alignedPtr = NULL;
    UINTPTR intSave = LOS_IntLock();
    LosMemDynNode *allocNode = NULL;
    do {
        if ((pool == NULL) || (size == 0) || boundary == 0 || !IS_POW_TWO(boundary) ||
            !IS_ALIGNED(boundary, sizeof(VOID *))) {
            break;
        }
        /* sizeof(gapSize) bytes stores offset between alignedPtr and ptr,
        the ptr has been OS_MEM_ALIGN_SIZE(4 or 8) aligned, so maximum
        offset between alignedPtr and ptr is boundary - OS_MEM_ALIGN_SIZE */
        if ((boundary - sizeof(gapSize)) > (((UINT32)-1) - size)) {
            break;
        }

        useSize = size + boundary - sizeof(gapSize);

        if (OS_MEM_NODE_GET_USED_FLAG(useSize) || OS_MEM_NODE_GET_ALIGNED_FLAG(useSize)) {
            break;
        }

        ptr = OsMemAllocWithCheck(pool, useSize);

        alignedPtr = (VOID *)OS_MEM_ALIGN(ptr, boundary);

        if (ptr == alignedPtr) {
            break;
        }

        /* store gapSize in address (ptr -4), it will be checked while free */
        gapSize = (UINT32)((AARCHPTR)alignedPtr - (AARCHPTR)ptr);
        allocNode = (LosMemDynNode *)ptr - 1;
        OS_MEM_NODE_SET_ALIGNED_FLAG(allocNode->selfNode.sizeAndFlag);
#ifdef LOSCFG_MEM_RECORDINFO
        allocNode->selfNode.originSize = size;
#endif
#ifdef LOSCFG_MEM_HEAD_BACKUP
        OsMemNodeSaveWithGapSize(allocNode, gapSize);
#endif

        OS_MEM_NODE_SET_ALIGNED_FLAG(gapSize);
        *((UINT32 *)((AARCHPTR)alignedPtr - sizeof(gapSize))) = gapSize;

        ptr = alignedPtr;

    } while (0);
#ifdef LOSCFG_MEM_RECORDINFO
    OsMemRecordMalloc(ptr, size);
#endif
    LOS_IntRestore(intSave);

    return ptr;
}

/*****************************************************************************
 Function : LOS_MemFree
 Description : free the node from memory & if there are free node beside, merger them.
                    at last update "listNodeHead' which saved all free node control head
 Input       : pool --Pointer to memory pool
                  ptr -- the node which need be freed
 Output      : None
 Return      : LOS_OK -Ok,  LOS_NOK -failed
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
{
    UINT32 ret = LOS_NOK;
    UINT32 gapSize = 0;
    UINTPTR intSave = LOS_IntLock();
#ifdef LOSCFG_MEM_HEAD_BACKUP
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    LosMemDynNode *startNode = OS_MEM_FIRST_NODE(pool);
    LosMemDynNode *endNode = OS_MEM_END_NODE(pool, poolInfo->poolSize);
#endif
    do {
        LosMemDynNode *node = (LosMemDynNode *)NULL;

        if ((pool == NULL) || (ptr == NULL) ||
            (!IS_ALIGNED(pool, sizeof(VOID *))) || (!IS_ALIGNED(ptr, sizeof(VOID *)))) {
            break;
        }

        gapSize = *((UINT32 *)((AARCHPTR)ptr - sizeof(UINT32)));
        if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize) && OS_MEM_NODE_GET_USED_FLAG(gapSize)) {
            PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FILE__, __LINE__, gapSize);
            break;
        }

        node = (LosMemDynNode *)((AARCHPTR)ptr - OS_MEM_NODE_HEAD_SIZE);

#ifdef LOSCFG_MEM_HEAD_BACKUP
        if (OS_MEM_MIDDLE_ADDR(startNode, node, endNode)) {
            if (OsMemChecksumVerify(&(node->selfNode)) &&
                OsMemChecksumVerify(&(node->backupNode))) {
                goto DO_FREE;
            }
        }
#endif

        if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize)) {
            gapSize = OS_MEM_NODE_GET_ALIGNED_GAPSIZE(gapSize);
            if ((gapSize & (OS_MEM_ALIGN_SIZE - 1)) || gapSize > (AARCHPTR)ptr - OS_MEM_NODE_HEAD_SIZE) {
                PRINT_ERR("illegal gapSize: 0x%x\n", gapSize);
#ifdef LOSCFG_MEM_HEAD_BACKUP
                /* try to restore from a broken GapSize node */
                if (OsMemBackupTryRestore(pool, &node, ptr) == LOS_OK) {
                    goto DO_FREE;
                }
#endif

                break;
            }
            node = (LosMemDynNode *)((AARCHPTR)ptr - gapSize - OS_MEM_NODE_HEAD_SIZE);

#ifdef LOSCFG_MEM_HEAD_BACKUP
            if (OS_MEM_MIDDLE_ADDR(startNode, node, endNode)) {
                /* GapSize maybe legal, but node head is broken */
                if (!OsMemChecksumVerify(&(node->selfNode))) {
                    node = (LosMemDynNode *)((AARCHPTR)ptr - OS_MEM_NODE_HEAD_SIZE);
                    if (OsMemBackupTryRestore(pool, &node, ptr) != LOS_OK) {
                        break;
                    }
                }
            }
#endif
        }
#ifdef LOSCFG_MEM_HEAD_BACKUP
        else {
            if (OS_MEM_MIDDLE_ADDR(startNode, node, endNode)) {
                /* GapSize is bad, we need to verify & try to restore */
                if (!OsMemChecksumVerify(&(node->selfNode))) {
                    node = (LosMemDynNode *)((AARCHPTR)ptr - OS_MEM_NODE_HEAD_SIZE);
                    if (OsMemBackupTryRestore(pool, &node, ptr) == LOS_OK) {
                        goto DO_FREE;
                    }
                    break;
                }
            }
        }

DO_FREE:
#endif
        ret = OsMemCheckUsedNode(pool, node);
        if (ret == LOS_OK) {
#ifdef LOSCFG_MEM_RECORDINFO
            OsMemRecordFree(ptr, node->selfNode.originSize);
#endif
            osMemFreeNode(node, pool);
        }

    } while (0);
#ifdef LOSCFG_MEM_RECORDINFO
    if (ret == LOS_NOK) {
        OsMemRecordFree(ptr, 0);
    }
#endif
    LOS_IntRestore(intSave);
    return ret;
}

/*****************************************************************************
 Function : LOS_MemRealloc
 Description : reAlloc memory node
 Input       : pool    --- Pointer to memory pool
                  ptr  --- pointer to memory node which will be realloced
                 size  --- the size of new node
 Output      : None
 Return      : Pointer to allocated memory
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size)
{
    UINTPTR intSave;
    UINT32 gapSize = 0;
    VOID *newPtr = NULL;
#ifdef LOSCFG_MEM_RECORDINFO
    VOID *originPtr = ptr;
#endif

    if ((INT32)size < 0) {
        return NULL;
    }

    intSave = LOS_IntLock();

    do {
        LosMemDynNode *node = (LosMemDynNode *)NULL;
        UINT32 ret;
        UINT32 allocSize;
        UINT32 nodeSize;
        LosMemDynNode *nextNode = (LosMemDynNode *)NULL;

        if (ptr == NULL) {
            newPtr = LOS_MemAlloc((VOID *)pool, (UINT32)size);
            break;
        }

        if (size == 0) {
            (VOID)LOS_MemFree((VOID *)pool, (VOID *)ptr);
            break;
        }

        gapSize = *((UINT32 *)((AARCHPTR)ptr - sizeof(UINT32)));
        if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize) && OS_MEM_NODE_GET_USED_FLAG(gapSize)) {
#ifdef LOSCFG_MEM_RECORDINFO
            OsMemRecordFree(originPtr, 0);
#endif
            PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FILE__, __LINE__, gapSize);
            break;
        }
        if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize)) {
            gapSize = OS_MEM_NODE_GET_ALIGNED_GAPSIZE(gapSize);
            if ((gapSize & (OS_MEM_ALIGN_SIZE - 1)) ||
                gapSize > ((AARCHPTR)ptr - OS_MEM_NODE_HEAD_SIZE - (AARCHPTR)pool)) {
                PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FILE__, __LINE__, gapSize);
#ifdef LOSCFG_MEM_RECORDINFO
                OsMemRecordFree(originPtr, 0);
#endif
                break;
            }
            ptr = (VOID *)((AARCHPTR)ptr - (AARCHPTR)gapSize);
        }
        node = (LosMemDynNode *)((AARCHPTR)ptr - OS_MEM_NODE_HEAD_SIZE);
        ret = OsMemCheckUsedNode(pool, node);
        if (ret != LOS_OK) {
#ifdef LOSCFG_MEM_RECORDINFO
            OsMemRecordFree(originPtr, 0);
#endif
            break;
        }

        allocSize = OS_MEM_ALIGN(size + OS_MEM_NODE_HEAD_SIZE, OS_MEM_ALIGN_SIZE);
        nodeSize = OS_MEM_NODE_GET_SIZE(node->selfNode.sizeAndFlag);
        if (nodeSize >= allocSize) {
#ifdef LOSCFG_MEM_RECORDINFO
            OsMemRecordFree(originPtr, node->selfNode.originSize);
#endif
            osMemReAllocSmaller(pool, allocSize, node, nodeSize);
#ifdef LOSCFG_MEM_RECORDINFO
            node->selfNode.originSize = size;
#ifdef LOSCFG_MEM_HEAD_BACKUP
            OsMemNodeSave(node);
#endif
            OsMemRecordMalloc(ptr, size);
#endif
            newPtr = ptr;
            break;
        }

        nextNode = OS_MEM_NEXT_NODE(node);
        if ((!OS_MEM_NODE_GET_USED_FLAG(nextNode->selfNode.sizeAndFlag)) &&
            ((nextNode->selfNode.sizeAndFlag + nodeSize) >= allocSize)) {
#ifdef LOSCFG_MEM_RECORDINFO
            OsMemRecordFree(originPtr, node->selfNode.originSize);
#endif
            OsMemMergeNodeForReAllocBigger(pool, allocSize, node, nodeSize, nextNode);
#ifdef LOSCFG_MEM_RECORDINFO
            node->selfNode.originSize = size;
#ifdef LOSCFG_MEM_HEAD_BACKUP
            OsMemNodeSave(node);
#endif
            OsMemRecordMalloc(ptr, size);
#endif
            newPtr = ptr;
            break;
        }

        newPtr = OsMemAllocWithCheck(pool, size);
        if (newPtr != NULL) {
#ifdef LOSCFG_MEM_RECORDINFO
            OsMemRecordMalloc(newPtr, size);
#endif
            if (memcpy_s(newPtr, size, ptr, (nodeSize - OS_MEM_NODE_HEAD_SIZE)) != 0) {
                (VOID)LOS_MemFree((VOID *)pool, (VOID *)newPtr);
                LOS_IntRestore(intSave);
                return NULL;
            }
#ifdef LOSCFG_MEM_RECORDINFO
            OsMemRecordFree(originPtr, node->selfNode.originSize);
#endif
            osMemFreeNode(node, pool);
        }
    } while (0);

    LOS_IntRestore(intSave);
    return newPtr;
}

/*****************************************************************************
 Function : LOS_MemTotalUsedGet
 Description : figure the pointer memory pool for it's total mem used
 Input       : pool    --- Pointer to memory pool
 Output      : None
 Return      : the size of the pool has been used
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemTotalUsedGet(VOID *pool)
{
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    UINT32 memUsed = 0;
    UINTPTR intSave;

    if (pool == NULL) {
        return LOS_NOK;
    }

    intSave = LOS_IntLock();

    for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= OS_MEM_END_NODE(pool, poolInfo->poolSize);
         tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        if (OS_MEM_NODE_GET_USED_FLAG(tmpNode->selfNode.sizeAndFlag)) {
            memUsed += OS_MEM_NODE_GET_SIZE(tmpNode->selfNode.sizeAndFlag);
        }
    }

    LOS_IntRestore(intSave);

    return memUsed;
}

/*****************************************************************************
 Function : LOS_MemUsedBlksGet
 Description : get the number of used node
 Input       : pool    --- Pointer to memory pool
 Output      : None
 Return      : the number of used node
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemUsedBlksGet(VOID *pool)
{
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    UINT32 blkNums = 0;
    UINTPTR intSave;

    if (pool == NULL) {
        return LOS_NOK;
    }

    intSave = LOS_IntLock();

    for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= OS_MEM_END_NODE(pool, poolInfo->poolSize);
         tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        if (OS_MEM_NODE_GET_USED_FLAG(tmpNode->selfNode.sizeAndFlag)) {
            blkNums++;
        }
    }

    LOS_IntRestore(intSave);

    return blkNums;
}

/*****************************************************************************
 Function :LOS_MemTaskIdGet
 Description : get a memory node's taskID if pointer node is "used node"
 Input       : ptr   --- pointer to aim node
 Output      : None
 Return      : taskID --Ok or OS_INVALID --pointer node is illegal or free node
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemTaskIdGet(VOID *ptr)
{
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)m_aucSysMem1;
    UINTPTR intSave;
#ifdef LOSCFG_EXC_INTERACTION
    if (ptr < (VOID *)m_aucSysMem1) {
        poolInfo = (LosMemPoolInfo *)m_aucSysMem0;
    }
#endif
    if (ptr == NULL ||
        ptr < (VOID *)OS_MEM_FIRST_NODE(poolInfo) ||
        ptr > (VOID *)OS_MEM_END_NODE(poolInfo, poolInfo->poolSize)) {
        PRINT_ERR("input ptr %p is out of system memory range[%p, %p]\n", ptr, OS_MEM_FIRST_NODE(poolInfo),
                  OS_MEM_END_NODE(poolInfo, poolInfo->poolSize));
        return OS_INVALID;
    }

    intSave = LOS_IntLock();

    for (tmpNode = OS_MEM_FIRST_NODE(poolInfo); tmpNode <= OS_MEM_END_NODE(poolInfo, poolInfo->poolSize);
         tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        if ((AARCHPTR)ptr < (AARCHPTR)tmpNode) {
            if (OS_MEM_NODE_GET_USED_FLAG((tmpNode->selfNode.preNode)->selfNode.sizeAndFlag)) {
                LOS_IntRestore(intSave);
                return (UINT32)((AARCHPTR)((tmpNode->selfNode.preNode)->selfNode.freeNodeInfo.pstNext));
            } else {
                LOS_IntRestore(intSave);
                PRINT_ERR("input ptr %p is belong to a free mem node\n", ptr);
                return OS_INVALID;
            }
        }
    }
    LOS_IntRestore(intSave);
    return OS_INVALID;
}

/*****************************************************************************
 Function : LOS_MemFreeBlksGet
 Description : get the number of free node
 Input       : pool    --- Pointer to memory pool
 Output      : None
 Return      : the number of free node
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemFreeBlksGet(VOID *pool)
{
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    UINT32 blkNums = 0;
    UINTPTR intSave;

    if (pool == NULL) {
        return LOS_NOK;
    }

    intSave = LOS_IntLock();

    for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= OS_MEM_END_NODE(pool, poolInfo->poolSize);
         tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        if (!OS_MEM_NODE_GET_USED_FLAG(tmpNode->selfNode.sizeAndFlag)) {
            blkNums++;
        }
    }

    LOS_IntRestore(intSave);

    return blkNums;
}

/*****************************************************************************
 Function : LOS_MemLastUsedGet
 Description : get the address of last used node(except end node)
 Input       : pool    --- Pointer to memory pool
 Output      : None
 Return      : address of last node offset sizeof(LosMemDynNode), if last node is freeNode
                   address of the end node, if last node is usedNode
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR AARCHPTR LOS_MemLastUsedGet(VOID *pool)
{
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    LosMemDynNode *node = (LosMemDynNode *)NULL;

    if (pool == NULL) {
        return LOS_NOK;
    }

    node = OS_MEM_END_NODE(pool, poolInfo->poolSize)->selfNode.preNode;

    if (OS_MEM_NODE_GET_USED_FLAG(node->selfNode.sizeAndFlag)) {
        return (AARCHPTR)((CHAR *) node + OS_MEM_NODE_GET_SIZE(node->selfNode.sizeAndFlag) + sizeof(LosMemDynNode));
    } else {
        return (AARCHPTR)((CHAR *) node + sizeof(LosMemDynNode));
    }
}

/*****************************************************************************
 Function : OsMemResetEndNode
 Description : reset "end node"
 Input       : pool    --- Pointer to memory pool
 Input       : preAddr    --- Pointer to the pre Pointer of end node
 Output      : endNode -- pointer to "end node"
 Return      : the number of free node
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID OsMemResetEndNode(VOID *pool, AARCHPTR preAddr)
{
    LosMemDynNode *endNode = (LosMemDynNode *)OS_MEM_END_NODE(pool, ((LosMemPoolInfo *)pool)->poolSize);
    endNode->selfNode.sizeAndFlag = OS_MEM_NODE_HEAD_SIZE;
    if (preAddr != (AARCHPTR)NULL) {
        endNode->selfNode.preNode = (LosMemDynNode *)(preAddr - sizeof(LosMemDynNode));
    }
    OS_MEM_NODE_SET_USED_FLAG(endNode->selfNode.sizeAndFlag);
    OsMemSetMagicNumAndTaskID(endNode);

#ifdef LOSCFG_MEM_HEAD_BACKUP
    OsMemNodeSave(endNode);
#endif
}

/*****************************************************************************
 Function : LOS_MemPoolSizeGet
 Description : get the memory pool's size
 Input       : pool    --- Pointer to memory pool
 Output      : LOS_NOK & Other value -- The size of the memory pool.
 Return      : the size of the memory pool
*****************************************************************************/
UINT32 LOS_MemPoolSizeGet(const VOID *pool)
{
    if (pool == NULL) {
        return LOS_NOK;
    }
    return ((LosMemPoolInfo *)pool)->poolSize;
}

LITE_OS_SEC_TEXT_MINOR VOID OsMemInfoPrint(VOID *pool)
{
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    LOS_MEM_POOL_STATUS status = { 0 };

    if (LOS_NOK == LOS_MemInfoGet(pool, &status)) {
        return;
    }

#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    PRINTK("pool addr          pool size    used size     free size    "
           "max free node size   used node num     free node num      UsageWaterLine\n"
           "---------------    --------     -------       --------     "
           "--------------       -------------      ------------      ------------\n"
           "%-16p   0x%-8x   0x%-8x    0x%-8x   0x%-16x   0x%-13x    0x%-13x    0x%-13x\n",
           poolInfo->pool, poolInfo->poolSize, status.uwTotalUsedSize,
           status.uwTotalFreeSize, status.uwMaxFreeNodeSize, status.uwUsedNodeNum,
           status.uwFreeNodeNum, status.usageWaterLine);

#else
    PRINTK("pool addr          pool size    used size     free size    "
           "max free node size   used node num     free node num\n"
           "---------------    --------     -------       --------     "
           "--------------       -------------      ------------\n"
           "%-16p   0x%-8x   0x%-8x    0x%-8x   0x%-16x   0x%-13x    0x%-13x\n",
           poolInfo->pool, poolInfo->poolSize, status.uwTotalUsedSize,
           status.uwTotalFreeSize, status.uwMaxFreeNodeSize, status.uwUsedNodeNum,
           status.uwFreeNodeNum);
#endif
    return;
}

LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus)
{
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    UINT32 totalUsedSize = 0;
    UINT32 totalFreeSize = 0;
    UINT32 maxFreeNodeSize = 0;
    UINT32 usedNodeNum = 0;
    UINT32 freeNodeNum = 0;
    UINTPTR intSave;

    if (poolStatus == NULL) {
        PRINT_ERR("can't use NULL addr to save info\n");
        return LOS_NOK;
    }

    if (poolInfo == NULL || (AARCHPTR)pool != (AARCHPTR)poolInfo->pool) {
        PRINT_ERR("wrong mem pool addr: %p, line:%d\n", poolInfo, __LINE__);
        return LOS_NOK;
    }

    tmpNode = (LosMemDynNode *)OS_MEM_END_NODE(pool, poolInfo->poolSize);
    tmpNode = (LosMemDynNode *)OS_MEM_ALIGN(tmpNode, OS_MEM_ALIGN_SIZE);

    if (!OS_MEM_MAGIC_VALID(tmpNode->selfNode.freeNodeInfo.pstPrev)) {
        PRINT_ERR("wrong mem pool addr: %p\n, line:%d", poolInfo, __LINE__);
        return LOS_NOK;
    }

    intSave = LOS_IntLock();

    for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= OS_MEM_END_NODE(pool, poolInfo->poolSize);
         tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        if (!OS_MEM_NODE_GET_USED_FLAG(tmpNode->selfNode.sizeAndFlag)) {
            ++freeNodeNum;
            totalFreeSize += OS_MEM_NODE_GET_SIZE(tmpNode->selfNode.sizeAndFlag);
            if (maxFreeNodeSize < OS_MEM_NODE_GET_SIZE(tmpNode->selfNode.sizeAndFlag)) {
                maxFreeNodeSize = OS_MEM_NODE_GET_SIZE(tmpNode->selfNode.sizeAndFlag);
            }
        } else {
            ++usedNodeNum;
            totalUsedSize += OS_MEM_NODE_GET_SIZE(tmpNode->selfNode.sizeAndFlag);
        }
    }

    LOS_IntRestore(intSave);

    poolStatus->uwTotalUsedSize = totalUsedSize;
    poolStatus->uwTotalFreeSize = totalFreeSize;
    poolStatus->uwMaxFreeNodeSize = maxFreeNodeSize;
    poolStatus->uwUsedNodeNum = usedNodeNum;
    poolStatus->uwFreeNodeNum = freeNodeNum;
#if defined(OS_MEM_WATERLINE) && (OS_MEM_WATERLINE == YES)
    poolStatus->uwUsageWaterLine = poolInfo->poolWaterLine;
#endif
    return LOS_OK;
}

LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemFreeNodeShow(VOID *pool)
{
    LOS_DL_LIST *listNodeHead = (LOS_DL_LIST *)NULL;
    LosMultipleDlinkHead *headAddr = (LosMultipleDlinkHead *)((AARCHPTR)pool + sizeof(LosMemPoolInfo));
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    UINT32 count, linkHeadIndex;
    UINT32 countNum[COLUMN_NUM] = { 0 };
    UINTPTR intSave;
    UINT32 index = 0;
    UINT32 indexTmp = 0;

    if (poolInfo == NULL || (AARCHPTR)pool != (AARCHPTR)poolInfo->pool) {
        PRINT_ERR("wrong mem pool addr: %p, line:%d\n", poolInfo, __LINE__);
        return LOS_NOK;
    }

    tmpNode = (LosMemDynNode *)OS_MEM_END_NODE(pool, poolInfo->poolSize);
    tmpNode = (LosMemDynNode *)OS_MEM_ALIGN(tmpNode, OS_MEM_ALIGN_SIZE);

    if (!OS_MEM_MAGIC_VALID(tmpNode->selfNode.freeNodeInfo.pstPrev)) {
        PRINT_ERR("wrong mem pool addr: %p, line:%d\n", poolInfo, __LINE__);
        return LOS_NOK;
    }
    PRINTK("\n   ************************ left free node number**********************\n");
    PRINTK("    block size:  ");
    intSave = LOS_IntLock();

    for (linkHeadIndex = 0; linkHeadIndex <= (OS_MULTI_DLNK_NUM - 1);
         linkHeadIndex++, indexTmp++) {
        count = 0;
        listNodeHead = headAddr->listHead[linkHeadIndex].pstNext;
        while (listNodeHead != &(headAddr->listHead[linkHeadIndex])) {
            listNodeHead = listNodeHead->pstNext;
            ++count;
        }
        PRINTK("2^%-5d", linkHeadIndex + OS_MIN_MULTI_DLNK_LOG2);
        if (linkHeadIndex != 0 && ((linkHeadIndex + 1) % COLUMN_NUM == 0 ||
            linkHeadIndex == (OS_MULTI_DLNK_NUM - 1))) {
            PRINTK("\n    node number:");
            for (index = 0; index < COLUMN_NUM; index++) {
                PRINTK("  %-5d", countNum[index]);
                if (linkHeadIndex == (OS_MULTI_DLNK_NUM - 1) &&
                    index == ((OS_MULTI_DLNK_NUM - 1) % COLUMN_NUM)) {
                    break;
                }
            }
            if (linkHeadIndex != (OS_MULTI_DLNK_NUM - 1)) {
                PRINTK("\n\n    block size:  ");
            }
        }

        indexTmp = linkHeadIndex % COLUMN_NUM;
        countNum[indexTmp] = count;
    }
    LOS_IntRestore(intSave);
    PRINTK("\n   ********************************************************************\n\n");

    return LOS_OK;
}
#ifdef LOSCFG_MEM_LEAKCHECK
LITE_OS_SEC_TEXT_MINOR VOID OsMemUsedNodeShow(VOID *pool)
{
    LosMemDynNode *tmpNode = (LosMemDynNode *)NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    UINTPTR intSave;
    UINT32 count;
    if (pool == NULL) {
        PRINTK("input param is NULL\n");
        return;
    }
    if (LOS_MemIntegrityCheck(pool)) {
        PRINTK("LOS_MemIntegrityCheck error\n");
        return;
    }
    intSave = LOS_IntLock();
#ifdef __LP64__
    PRINTK("node                ");
#else
    PRINTK("node        ");
#endif
    for (count = 0; count < LOS_RECORD_LR_CNT; count++) {
#ifdef __LP64__
        PRINTK("        LR[%d]       ", count);
#else
        PRINTK("    LR[%d]   ", count);
#endif
    }
    PRINTK("\n");
    for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode < OS_MEM_END_NODE(pool, poolInfo->poolSize);
         tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
        if (OS_MEM_NODE_GET_USED_FLAG(tmpNode->selfNode.sizeAndFlag)) {
#ifdef __LP64__
            PRINTK("%018p: ", tmpNode);
#else
            PRINTK("%010p: ", tmpNode);
#endif
            for (count = 0; count < LOS_RECORD_LR_CNT; count++) {
#ifdef __LP64__
                PRINTK(" %018p ", tmpNode->selfNode.linkReg[count]);
#else
                PRINTK(" %010p ", tmpNode->selfNode.linkReg[count]);
#endif
            }
            PRINTK("\n");
        }
    }
    LOS_IntRestore(intSave);
    return;
}
#endif

#ifdef LOSCFG_BASE_MEM_NODE_SIZE_CHECK

/*****************************************************************************
  Function: LOS_MemNodeSizeCheck
  Description: get a node's(ptr) size ,include total size and available size
  Input        :pool --which pool doesn't your ptr belong to
                   ptr --point to source node
  Output      :totalSize -- save total size
                   availSize -- save availabe size
  Return : errorID or LOS_OK
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemNodeSizeCheck(VOID *pool, VOID *ptr, UINT32 *totalSize, UINT32 *availSize)
{
    VOID *head = NULL;
    LosMemPoolInfo *poolInfo = (LosMemPoolInfo *)pool;
    UINT8 *endPool = (UINT8 *)NULL;

    if (g_memCheckLevel == LOS_MEM_CHECK_LEVEL_DISABLE) {
        return LOS_ERRNO_MEMCHECK_DISABLED;
    }

    if ((pool == NULL) || (ptr == NULL)) {
        return LOS_ERRNO_MEMCHECK_PARA_NULL;
    }

    endPool = (UINT8 *)pool + poolInfo->poolSize;
    if (!(OS_MEM_MIDDLE_ADDR_OPEN_END(pool, (UINT8 *)ptr, endPool))) {
        return LOS_ERRNO_MEMCHECK_OUTSIDE;
    }

    if (g_memCheckLevel == LOS_MEM_CHECK_LEVEL_HIGH) {
        head = OsMemFindNodeCtrl(ptr);
        if ((head == NULL) ||
            (OS_MEM_NODE_GET_SIZE(((LosMemDynNode *)head)->selfNode.sizeAndFlag) < ((AARCHPTR)ptr - (AARCHPTR)head))) {
            return LOS_ERRNO_MEMCHECK_NO_HEAD;
        }
        *totalSize = OS_MEM_NODE_GET_SIZE(((LosMemDynNode *)head)->selfNode.sizeAndFlag - sizeof(LosMemDynNode));
        *availSize = OS_MEM_NODE_GET_SIZE(((LosMemDynNode *)head)->selfNode.sizeAndFlag - ((AARCHPTR)ptr -
                                          (AARCHPTR)head));
        return LOS_OK;
    }
    if (g_memCheckLevel == LOS_MEM_CHECK_LEVEL_LOW) {
        if (ptr != (VOID *)OS_MEM_ALIGN(ptr, OS_MEM_ALIGN_SIZE)) {
            return LOS_ERRNO_MEMCHECK_NO_HEAD;
        }
        head = (VOID *)((AARCHPTR)ptr - sizeof(LosMemDynNode));
        if (OS_MEM_MAGIC_VALID(((LosMemDynNode *)head)->selfNode.freeNodeInfo.pstPrev)) {
            *totalSize = OS_MEM_NODE_GET_SIZE(((LosMemDynNode *)head)->selfNode.sizeAndFlag - sizeof(LosMemDynNode));
            *availSize = OS_MEM_NODE_GET_SIZE(((LosMemDynNode *)head)->selfNode.sizeAndFlag - sizeof(LosMemDynNode));
            return LOS_OK;
        } else {
            return LOS_ERRNO_MEMCHECK_NO_HEAD;
        }
    }

    return LOS_ERRNO_MEMCHECK_WRONG_LEVEL;
}

/*****************************************************************************
Function     : OsMemFindNodeCtrl
Description : get a pool's memCtrl
Input         :ptr -- point to source ptr
Output       :None
Return        : search forward for ptr's memCtrl or "NULL"
@attention : this func couldn't ensure the return memCtrl belongs to ptr
it just find forward the most nearly one
*******************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID *OsMemFindNodeCtrl(VOID *ptr)
{
    UINT8 *head = (UINT8 *)ptr;

    if (ptr == NULL) {
        return NULL;
    }

    head = (UINT8 *)OS_MEM_ALIGN((VOID *)head, OS_MEM_ALIGN_SIZE);
    while (!OS_MEM_MAGIC_VALID(((LosMemDynNode *)head)->selfNode.freeNodeInfo.pstPrev)) {
        head -= sizeof(AARCHPTR);
    }
    return head;
}

/*****************************************************************************
 Function : LOS_MemCheckLevelSet
 Description : setting g_memCheckLevel which decide the manner of memcheck
 Input       : checkLevel -- what level want to set
 Output      : None
 Return      : LOS_OK -- setting succeed
                  OS_ERRNO_MEMCHECK_WRONG_LEVEL -- setting failed due to illegal parameter
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemCheckLevelSet(UINT8 checkLevel)
{
    if (checkLevel == LOS_MEM_CHECK_LEVEL_LOW) {
        PRINTK("%s: LOS_MEM_CHECK_LEVEL_LOW \n", __FUNCTION__);
    } else if (checkLevel == LOS_MEM_CHECK_LEVEL_HIGH) {
        PRINTK("%s: LOS_MEM_CHECK_LEVEL_HIGH \n", __FUNCTION__);
    } else if (checkLevel == LOS_MEM_CHECK_LEVEL_DISABLE) {
        PRINTK("%s: LOS_MEM_CHECK_LEVEL_DISABLE \n", __FUNCTION__);
    } else {
        PRINTK("%s: wrong para, setting failed !! \n", __FUNCTION__);
        return LOS_ERRNO_MEMCHECK_WRONG_LEVEL;
    }
    g_memCheckLevel = checkLevel;
    return LOS_OK;
}

LITE_OS_SEC_TEXT_MINOR UINT8 LOS_MemCheckLevelGet(VOID)
{
    return g_memCheckLevel;
}

#endif /* LOSCFG_BASE_MEM_NODE_SIZE_CHECK */

UINT32 osMemSysNodeCheck(VOID *dstAddr, VOID *srcAddr, UINT32 nodeLength, UINT8 pos)
{
#ifdef LOSCFG_BASE_MEM_NODE_SIZE_CHECK
    UINT32 ret = 0;
    UINT32 totalSize = 0;
    UINT32 availSize = 0;
    UINT8 *pool = m_aucSysMem1;
#ifdef LOSCFG_EXC_INTERACTION
    if ((AARCHPTR)dstAddr < (AARCHPTR)m_aucSysMem0 + g_excInteractMemSize) {
        pool = m_aucSysMem0;
    }
#endif
    if (pos == 0) { /* if this func was called by memset */
        ret = LOS_MemNodeSizeCheck(pool, dstAddr, &totalSize, &availSize);
        if (ret == LOS_OK && nodeLength > availSize) {
            PRINT_ERR("---------------------------------------------\n");
            PRINT_ERR("memset: dst inode availSize is not enough"
                      " availSize = 0x%x nodeLength = 0x%x\n",
                      availSize, nodeLength);
            osBackTrace();
            PRINT_ERR("---------------------------------------------\n");
            return LOS_NOK;
        }
    } else if (pos == 1) { /* if this func was called by memcpy */
        ret = LOS_MemNodeSizeCheck(pool, dstAddr, &totalSize, &availSize);
        if (ret == LOS_OK && nodeLength > availSize) {
            PRINT_ERR("---------------------------------------------\n");
            PRINT_ERR("memcpy: dst inode availSize is not enough"
                      " availSize = 0x%x nodeLength = 0x%x\n",
                      availSize, nodeLength);
            osBackTrace();
            PRINT_ERR("---------------------------------------------\n");
            return LOS_NOK;
        }
#ifdef LOSCFG_EXC_INTERACTION
        if ((AARCHPTR)srcAddr < (AARCHPTR)m_aucSysMem0 + g_excInteractMemSize) {
            pool = m_aucSysMem0;
        } else {
            pool = m_aucSysMem1;
        }
#endif
        ret = LOS_MemNodeSizeCheck(pool, srcAddr, &totalSize, &availSize);
        if (ret == LOS_OK && nodeLength > availSize) {
            PRINT_ERR("---------------------------------------------\n");
            PRINT_ERR("memcpy: src inode availSize is not enough"
                      " availSize = 0x%x nodeLength = 0x%x\n",
                      availSize, nodeLength);
            osBackTrace();
            PRINT_ERR("---------------------------------------------\n");
            return LOS_NOK;
        }
    }
#endif
    return LOS_OK;
}

#ifdef LOSCFG_MEM_MUL_MODULE
STATIC INLINE UINT32 osMemModCheck(UINT32 moduleID)
{
    if (moduleID > MEM_MODULE_MAX) {
        PRINT_ERR("error module ID input!\n");
        return LOS_NOK;
    }
    return LOS_OK;
}

STATIC INLINE VOID *osMemPtrToNode(VOID *ptr)
{
    UINT32 gapSize;

    if ((AARCHPTR)ptr & (OS_MEM_ALIGN_SIZE - 1)) {
        PRINT_ERR("[%s:%d]ptr:%p not align by 4byte\n", __FILE__, __LINE__, ptr);
        return NULL;
    }

    gapSize = *((UINT32 *)((AARCHPTR)ptr - sizeof(UINT32)));
    if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize) && OS_MEM_NODE_GET_USED_FLAG(gapSize)) {
        PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FILE__, __LINE__, gapSize);
        return NULL;
    }
    if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize)) {
        gapSize = OS_MEM_NODE_GET_ALIGNED_GAPSIZE(gapSize);
        if ((gapSize & (OS_MEM_ALIGN_SIZE - 1)) || gapSize > ((AARCHPTR)ptr - OS_MEM_NODE_HEAD_SIZE)) {
            PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FILE__, __LINE__, gapSize);
            return NULL;
        }

        ptr = (VOID *)((AARCHPTR)ptr - gapSize);
    }

    return (VOID *)((AARCHPTR)ptr - OS_MEM_NODE_HEAD_SIZE);
}

STATIC INLINE UINT32 osMemNodeSizeGet(VOID *ptr)
{
    LosMemDynNode *node;
    node = (LosMemDynNode *)osMemPtrToNode(ptr);
    if (node == NULL) {
        return 0;
    }

    return OS_MEM_NODE_GET_SIZE(node->selfNode.sizeAndFlag);
}

VOID *LOS_MemMalloc(VOID *pool, UINT32 size, UINT32 moduleID)
{
    UINTPTR intSave;
    VOID *ptr = NULL;
    VOID *node = NULL;
    if (osMemModCheck(moduleID) == LOS_NOK) {
        return NULL;
    }
    ptr = LOS_MemAlloc(pool, size);
    if (ptr != NULL) {
        intSave = LOS_IntLock();
        g_moduleMemUsedSize[moduleID] += osMemNodeSizeGet(ptr);
        node = osMemPtrToNode(ptr);
        OS_MEM_MODID_SET(node, moduleID); /*lint !e613*/
        LOS_IntRestore(intSave);
    }
    return ptr;
}

VOID *LOS_MemMallocAlign(VOID *pool, UINT32 size, UINT32 boundary, UINT32 moduleID)
{
    UINTPTR intSave;
    VOID *ptr = NULL;
    VOID *node = NULL;
    if (osMemModCheck(moduleID) == LOS_NOK) {
        return NULL;
    }
    ptr = LOS_MemAllocAlign(pool, size, boundary);
    if (ptr != NULL) {
        intSave = LOS_IntLock();
        g_moduleMemUsedSize[moduleID] += osMemNodeSizeGet(ptr);
        node = osMemPtrToNode(ptr);
        OS_MEM_MODID_SET(node, moduleID); /*lint !e613*/
        LOS_IntRestore(intSave);
    }
    return ptr;
}

UINT32 LOS_MemMfree(VOID *pool, VOID *ptr, UINT32 moduleID)
{
    UINTPTR intSave;
    UINT32 ret;
    UINT32 size;
    LosMemDynNode *node;

    if (osMemModCheck(moduleID) == LOS_NOK || ptr == NULL) {
        return LOS_NOK;
    }

    node = (LosMemDynNode *)osMemPtrToNode(ptr);
    if (node == NULL) {
        return LOS_NOK;
    }

    size = OS_MEM_NODE_GET_SIZE(node->selfNode.sizeAndFlag);

    if (moduleID != OS_MEM_MODID_GET(node)) {
        PRINT_ERR("node[%p] alloced in module %d, but free in module %d\n node's taskID: 0x%x\n",
                  ptr, OS_MEM_MODID_GET(node), moduleID, OS_MEM_TASKID_GET(node));
        moduleID = OS_MEM_MODID_GET(node);
    }
    ret = LOS_MemFree(pool, ptr);

    if (ret == LOS_OK) {
        intSave = LOS_IntLock();
        g_moduleMemUsedSize[moduleID] -= size;
        LOS_IntRestore(intSave);
    }
    return ret;
}

VOID *LOS_MemMrealloc(VOID *pool, VOID *ptr, UINT32 size, UINT32 moduleID)
{
    VOID *newPtr = NULL;
    UINT32 oldNodeSize;
    UINTPTR intSave;
    LosMemDynNode *node = (LosMemDynNode *)NULL;
    UINT32 oldModuleID = moduleID;

    if (osMemModCheck(moduleID) == LOS_NOK) {
        return NULL;
    }

    if (ptr == NULL) {
        return LOS_MemMalloc(pool, size, moduleID);
    }

    node = (LosMemDynNode *)osMemPtrToNode(ptr);
    if (node == NULL) {
        return NULL;
    }

    if (moduleID != OS_MEM_MODID_GET(node)) {
        PRINT_ERR("a node[%p] alloced in module %d, but realloc in module %d\n node's taskID: %d\n",
                  ptr, OS_MEM_MODID_GET(node), moduleID, OS_MEM_TASKID_GET(node));
        oldModuleID = OS_MEM_MODID_GET(node);
    }

    if (size == 0) {
        (VOID)LOS_MemMfree(pool, ptr, oldModuleID);
        return NULL;
    }

    oldNodeSize = osMemNodeSizeGet(ptr);
    newPtr = LOS_MemRealloc(pool, ptr, size);
    if (newPtr != NULL) {
        intSave = LOS_IntLock();
        g_moduleMemUsedSize[moduleID] += osMemNodeSizeGet(newPtr);
        g_moduleMemUsedSize[oldModuleID] -= oldNodeSize;
        node = (LosMemDynNode *)osMemPtrToNode(newPtr);
        OS_MEM_MODID_SET(node, moduleID);
        LOS_IntRestore(intSave);
    }
    return newPtr;
}

UINT32 LOS_MemMusedGet(UINT32 moduleID)
{
    if (osMemModCheck(moduleID) == LOS_NOK) {
        return OS_NULL_INT;
    }
    return g_moduleMemUsedSize[moduleID];
}
#endif

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
